//===--- Integers.swift.gyb -----------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
%{
#
# Utility code for later in this template
#

from SwiftIntTypes import all_integer_types, int_max_bits, should_define_truncating_bit_pattern_init
from SwiftFloatingPointTypes import getFtoIBounds

from string import maketrans, capitalize
from itertools import chain

# Number of bits in the Builtin.Word type
word_bits = int(CMAKE_SIZEOF_VOID_P) * 8

# Number of bits in integer literals.
builtinIntLiteralBits = 2048
IntLiteral = 'Int%s' % builtinIntLiteralBits

class struct(object):
  def __init__(self, **kw):
    self.__dict__ = kw
  def __repr__(self):
    return 'struct(%r)' % self.__dict__

binaryArithmetic = {
  'Numeric' : [
    struct(operator='+', name='adding',      firstArg='_',  llvmName='add', kind='+'),
    struct(operator='-', name='subtracting', firstArg='_',  llvmName='sub', kind='-'),
    struct(operator='*', name='multiplied',  firstArg='by', llvmName='mul', kind='*'),
  ],
  'BinaryInteger' : [
    struct(operator='/', name='divided',     firstArg='by', llvmName='div', kind='/'),
    struct(operator='%', name='remainder',   firstArg='dividingBy', llvmName='rem', kind='/'),
  ],
}

binaryBitwise = [
    struct(operator='&', llvmName='and'),
    struct(operator='|', llvmName='or'),
    struct(operator='^', llvmName='xor'),
]

maskingShifts = [
    struct(
      operator='&>>', nonMaskingOperator='>>', description='right shift',
      helper='_nonMaskingRightShift',
      llvmName=lambda s:['lshr','ashr'][s]),
    struct(
      operator='&<<', nonMaskingOperator='<<', description='left shift',
      helper='_nonMaskingLeftShift',
      llvmName=lambda _: 'shl'),
]

IntMax = 'Int%s' % int_max_bits
UIntMax = 'UInt%s' % int_max_bits
}%

// FIXME(integers): remove these two aliases
/// The largest native signed integer type.
@available(swift, obsoleted: 4.0, renamed: "${IntMax}")
public typealias IntMax = ${IntMax}
/// The largest native unsigned integer type.
@available(swift, obsoleted: 4.0, renamed: "${UIntMax}")
public typealias UIntMax = ${UIntMax}

infix operator &<< : BitwiseShiftPrecedence
infix operator &<<= : AssignmentPrecedence
infix operator &>> : BitwiseShiftPrecedence
infix operator &>>= : AssignmentPrecedence

//===----------------------------------------------------------------------===//
//===--- Bits for the Stdlib ----------------------------------------------===//
//===----------------------------------------------------------------------===//

// FIXME(integers): This should go in the stdlib separately, probably.
extension ExpressibleByIntegerLiteral
  where Self : _ExpressibleByBuiltinIntegerLiteral {
  @_transparent
  public init(integerLiteral value: Self) {
    self = value
  }
}

//===----------------------------------------------------------------------===//
//===--- Documentation Helpers --------------------------------------------===//
//===----------------------------------------------------------------------===//

%{

# documentation for binary operators: +, -, <<, &, etc
def operatorComment(operator, fixedWidth):
    comments = {
        '+': """\
  /// Adds two values and produces their sum.
  ///
  /// The addition operator (`+`) calculates the sum of its two arguments. For
  /// example:
  ///
  ///     1 + 2                   // 3
  ///     -10 + 15                // 5
  ///     -15 + -5                // -20
  ///     21.5 + 3.25             // 24.75
  ///
  /// You cannot use `+` with arguments of different types. To add values of
  /// different types, convert one of the values to the other value's type.
  ///
  ///     let x: Int8 = 21
  ///     let y: Int = 1000000
  ///     Int(x) + y              // 1000021
  ///
""" + ("""\
  /// The sum of the two arguments must be representable in the arguments'
  /// type. In the following example, the result of `21 + 120` is greater than
  /// the maximum representable `Int8` value:
  ///
  ///     x + 120                 // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
  /// If you want to opt out of overflow checking and ignore any overflow, use
  /// the overflow addition operator (`&+`).
  ///
  ///     x &+ 120                // -115
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: The first value to add.
  ///   - rhs: The second value to add.
""",
        '-': """\
  /// Subtracts one value from another and produces their difference.
  ///
  /// The subtraction operator (`-`) calculates the difference of its two
  /// arguments. For example:
  ///
  ///     8 - 3                   // 5
  ///     -10 - 5                 // -15
  ///     100 - -5                // 105
  ///     10.5 - 100.0            // -89.5
  ///
  /// You cannot use `-` with arguments of different types. To subtract values
  /// of different types, convert one of the values to the other value's type.
  ///
  ///     let x: UInt8 = 21
  ///     let y: UInt = 1000000
  ///     y - UInt(x)             // 999979
  ///
""" + ("""\
  /// The difference of the two arguments must be representable in the
  /// arguments' type. In the following example, the result of `21 - 50` is
  /// less than zero, the minimum representable `UInt8` value:
  ///
  ///     x - 50                  // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
  /// If you want to opt out of overflow checking and ignore any overflow, use
  /// the overflow subtraction operator (`&-`).
  ///
  ///     x &- 50                // 227
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: A numeric value.
  ///   - rhs: The value to subtract from `lhs`.
""",
        '*': """\
  /// Multiplies two values and produces their product.
  ///
  /// The multiplication operator (`*`) calculates the product of its two
  /// arguments. For example:
  ///
  ///     2 * 3                   // 6
  ///     100 * 21                // 2100
  ///     -10 * 15                // -150
  ///     3.5 * 2.25              // 7.875
  ///
  /// You cannot use `*` with arguments of different types. To multiply values
  /// of different types, convert one of the values to the other value's type.
  ///
  ///     let x: Int8 = 21
  ///     let y: Int = 1000000
  ///     Int(x) * y              // 21000000
  ///
""" + ("""\
  /// The product of the two arguments must be representable in the arguments'
  /// type. In the following example, the result of `21 * 21` is greater than
  /// the maximum representable `Int8` value:
  ///
  ///     x * 21                  // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
  /// If you want to opt out of overflow checking and ignore any overflow, use
  /// the overflow multiplication operator (`&*`).
  ///
  ///     x &* 21                // -115
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: The first value to multiply.
  ///   - rhs: The second value to multiply.
""",
        '/': """\
  /// Returns the quotient of dividing the first value by the second.
  ///
  /// For integer types, any remainder of the division is discarded.
  ///
  ///     let x = 21 / 5
  ///     // x == 4
  ///
  /// - Parameters:
  ///   - lhs: The value to divide.
  ///   - rhs: The value to divide `lhs` by. `rhs` must not be zero.
""",
        '%': """\
  /// Returns the remainder of dividing the first value by the second.
  ///
  /// The result of the modulo operator (`%`) has the same sign as `lhs` and is
  /// less than `rhs.magnitude`.
  ///
  ///     let x = 22 % 5
  ///     // x == 2
  ///     let y = 22 % -5
  ///     // y == 2
  ///     let z = -22 % -5
  ///     // z == -2
  ///
  /// For any two integers `a` and `b`, their quotient `q`, and their remainder
  /// `r`, `a == b * q + r`.
  ///
  /// - Parameters:
  ///   - lhs: The value to divide.
  ///   - rhs: The value to divide `lhs` by. `rhs` must not be zero.
""",
        '&+': """\
  /// Returns the sum of the two given values, discarding any overflow.
  ///
  /// The masking addition operator (`&+`) silently discards any overflow that
  /// occurs during the operation. In the following example, the sum of `100`
  /// and `121` is greater than the maximum representable `Int8` value, so the
  /// result is the overflowed value:
  ///
  ///     let x: Int8 = 10 &+ 21
  ///     // x == 31
  ///     let y: Int8 = 100 &+ 121
  ///     // y == -35 (after overflow)
  ///
  /// - Parameters:
  ///   - lhs: The first value to add.
  ///   - rhs: The second value to add.
""",
        '&-': """\
  /// Returns the difference of the two given values, discarding any overflow.
  ///
  /// The masking subtraction operator (`&-`) silently discards any overflow
  /// that occurs during the operation. In the following example, the
  /// difference of `10` and `21` is less than zero, the minimum representable
  /// `UInt` value, so the result is the overflowed value:
  ///
  ///     let x: UInt8 = 21 &- 10
  ///     // x == 11
  ///     let y: UInt8 = 10 &- 21
  ///     // y == 245 (after overflow)
  ///
  /// - Parameters:
  ///   - lhs: A numeric value.
  ///   - rhs: The value to subtract from `lhs`.
""",
        '&*': """\
  /// Returns the product of the two given values, discarding any overflow.
  ///
  /// The masking multiplication operator (`&*`) silently discards any overflow
  /// that occurs during the operation. In the following example, the product
  /// of `10` and `50` is greater than the maximum representable `Int8` value,
  /// so the result is the overflowed value:
  ///
  ///     let x: Int8 = 10 &* 5
  ///     // x == 50
  ///     let y: Int8 = 10 &* 50
  ///     // y == -12 (after overflow)
  ///
  /// - Parameters:
  ///   - lhs: The first value to multiply.
  ///   - rhs: The second value to multiply.
""",
        '&': """\
  /// Returns the result of performing a bitwise AND operation on the two given
  /// values.
  ///
  /// A bitwise AND operation results in a value that has each bit set to `1`
  /// where *both* of its arguments have that bit set to `1`. For example:
  ///
  ///     let x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     let z = x & y             // 0b00000100
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '|': """\
  /// Returns the result of performing a bitwise OR operation on the two given
  /// values.
  ///
  /// A bitwise OR operation results in a value that has each bit set to `1`
  /// where *one or both* of its arguments have that bit set to `1`. For
  /// example:
  ///
  ///     let x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     let z = x | y             // 0b00001111
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '^': """\
  /// Returns the result of performing a bitwise XOR operation on the two given
  /// values.
  ///
  /// A bitwise XOR operation, also known as an exclusive OR operation, results
  /// in a value that has each bit set to `1` where *one or the other but not
  /// both* of its arguments had that bit set to `1`. For example:
  ///
  ///     let x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     let z = x ^ y             // 0b00001011
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '&>>': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the right, masking the shift amount to the
  /// type's bit width.
  ///
  /// The masking right shift operator (`&>>`) performs a *masking shift*,
  /// where the value passed as `rhs` is masked to produce a value in the
  /// range `0..<lhs.bitWidth`. The shift is performed using this masked
  /// value.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the shift amount requires no masking.
  ///
  ///     let x: UInt8 = 30                 // 0b00011110
  ///     let y = x &>> 2
  ///     // y == 7                         // 0b00000111
  ///
  /// However, if you use `19` as `rhs`, the operation first bitmasks `rhs` to
  /// `3`, and then uses that masked value as the number of bits to shift `lhs`.
  ///
  ///     let z = x &>> 19
  ///     // z == 3                         // 0b00000011
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the right. If `rhs` is
  ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
  ///     value within that range.
""",
        '&<<': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the left, masking the shift amount to the
  /// type's bit width.
  ///
  /// The masking left shift operator (`&<<`) performs a *masking shift*, where
  /// the value used as `rhs` is masked to produce a value in the range
  /// `0..<lhs.bitWidth`. The shift is performed using this masked value.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the shift amount requires no masking.
  ///
  ///     let x: UInt8 = 30                 // 0b00011110
  ///     let y = x &<< 2
  ///     // y == 120                       // 0b01111000
  ///
  /// However, if you pass `19` as `rhs`, the method first bitmasks `rhs` to
  /// `3`, and then uses that masked value as the number of bits to shift `lhs`.
  ///
  ///     let z = x &<< 19
  ///     // z == 240                       // 0b11110000
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the left. If `rhs` is
  ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
  ///     value within that range.
""",
        '>>': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the right.
  ///
  /// The `>>` operator performs a *smart shift*, which defines a result for a
  /// shift of any value.
  ///
  /// - Using a negative value for `rhs` performs a left shift using
  ///   `abs(rhs)`.
  /// - Using a value for `rhs` that is greater than or equal to the bit width
  ///   of `lhs` is an *overshift*. An overshift results in `-1` for a
  ///   negative value of `lhs` or `0` for a nonnegative value.
  /// - Using any other value for `rhs` performs a right shift on `lhs` by that
  ///   amount.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the value is shifted right by two bits.
  ///
  ///     let x: UInt8 = 30                 // 0b00011110
  ///     let y = x >> 2
  ///     // y == 7                         // 0b00000111
  ///
  /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits
  /// are set to zero.
  ///
  ///     let z = x >> 11
  ///     // z == 0                         // 0b00000000
  ///
  /// Using a negative value as `rhs` is the same as performing a left shift
  /// using `abs(rhs)`.
  ///
  ///     let a = x >> -3
  ///     // a == 240                       // 0b11110000
  ///     let b = x << 3
  ///     // b == 240                       // 0b11110000
  ///
  /// Right shift operations on negative values "fill in" the high bits with
  /// ones instead of zeros.
  ///
  ///     let q: Int8 = -30                 // 0b11100010
  ///     let r = q >> 2
  ///     // r == -8                        // 0b11111000
  ///
  ///     let s = q >> 11
  ///     // s == -1                        // 0b11111111
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the right.
""",
        '<<': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the left.
  ///
  /// The `<<` operator performs a *smart shift*, which defines a result for a
  /// shift of any value.
  ///
  /// - Using a negative value for `rhs` performs a right shift using
  ///   `abs(rhs)`.
  /// - Using a value for `rhs` that is greater than or equal to the bit width
  ///   of `lhs` is an *overshift*, resulting in zero.
  /// - Using any other value for `rhs` performs a left shift on `lhs` by that
  ///   amount.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the value is shifted left by two bits.
  ///
  ///     let x: UInt8 = 30                 // 0b00011110
  ///     let y = x << 2
  ///     // y == 120                       // 0b01111000
  ///
  /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits
  /// are set to zero.
  ///
  ///     let z = x << 11
  ///     // z == 0                         // 0b00000000
  ///
  /// Using a negative value as `rhs` is the same as performing a right shift
  /// with `abs(rhs)`.
  ///
  ///     let a = x << -3
  ///     // a == 3                         // 0b00000011
  ///     let b = x >> 3
  ///     // b == 3                         // 0b00000011
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the left.
""",
  }
    return comments[operator]

# documentation for assignment operators: +=, -=, <<=, etc
def assignmentOperatorComment(operator, fixedWidth):
    comments = {
        '+': """\
  /// Adds two values and stores the result in the left-hand-side variable.
  ///
""" + ("""\
  /// The sum of the two arguments must be representable in the arguments'
  /// type. In the following example, the result of `21 + 120` is greater than
  /// the maximum representable `Int8` value:
  ///
  ///     var x: Int8 = 21
  ///     x += 120
  ///     // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: The first value to add.
  ///   - rhs: The second value to add.
""",
        '-': """\
  /// Subtracts the second value from the first and stores the difference in the
  /// left-hand-side variable.
  ///
""" + ("""\
  /// The difference of the two arguments must be representable in the
  /// arguments' type. In the following example, the result of `21 - 50` is
  /// less than zero, the minimum representable `UInt8` value:
  ///
  ///     var x: UInt8 = 21
  ///     x - 50                  
  ///     // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: A numeric value.
  ///   - rhs: The value to subtract from `lhs`.
""",
        '*': """\
  /// Multiplies two values and stores the result in the left-hand-side 
  /// variable.
  ///
""" + ("""\
  /// The product of the two arguments must be representable in the arguments'
  /// type. In the following example, the result of `21 * 21` is greater than
  /// the maximum representable `Int8` value:
  ///
  ///     var x: Int8 = 21
  ///     x * 21                  
  ///     // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: The first value to multiply.
  ///   - rhs: The second value to multiply.
""",
        '/': """\
  /// Divides the first value by the second and stores the quotient in the
  /// left-hand-side variable.
  ///
  /// For integer types, any remainder of the division is discarded.
  ///
  ///     var x = 21
  ///     x /= 5
  ///     // x == 4
  ///
  /// - Parameters:
  ///   - lhs: The value to divide.
  ///   - rhs: The value to divide `lhs` by. `rhs` must not be zero.
""",
        '%': """\
  /// Divides the first value by the second and stores the remainder in the
  /// left-hand-side variable.
  ///
  /// The result has the same sign as `lhs` and is less than `rhs.magnitude`.
  ///
  ///     var x = 22
  ///     x %= 5
  ///     // x == 2
  ///
  ///     var y = 22
  ///     y %= -5
  ///     // y == 2
  ///
  ///     var z = -22 
  ///     z %= -5
  ///     // z == -2
  ///
  /// - Parameters:
  ///   - lhs: The value to divide.
  ///   - rhs: The value to divide `lhs` by. `rhs` must not be zero.
""",
        '&': """\
  /// Stores the result of performing a bitwise AND operation on the two given
  /// values in the left-hand-side variable.
  ///
  /// A bitwise AND operation results in a value that has each bit set to `1`
  /// where *both* of its arguments have that bit set to `1`. For example:
  ///
  ///     var x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     x &= y                    // 0b00000100
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '|': """\
  /// Stores the result of performing a bitwise OR operation on the two given
  /// values in the left-hand-side variable.
  ///
  /// A bitwise OR operation results in a value that has each bit set to `1`
  /// where *one or both* of its arguments have that bit set to `1`. For
  /// example:
  ///
  ///     var x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     x |= y                    // 0b00001111
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '^': """\
  /// Stores the result of performing a bitwise XOR operation on the two given
  /// values in the left-hand-side variable.
  ///
  /// A bitwise XOR operation, also known as an exclusive OR operation, results
  /// in a value that has each bit set to `1` where *one or the other but not
  /// both* of its arguments had that bit set to `1`. For example:
  ///
  ///     var x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     x ^= y                    // 0b00001011
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '&>>': """\
  /// Calculates the result of shifting a value's binary representation the
  /// specified number of digits to the right, masking the shift amount to the
  /// type's bit width, and stores the result in the left-hand-side variable.
  ///
  /// The `&>>=` operator performs a *masking shift*, where the value passed as
  /// `rhs` is masked to produce a value in the range `0..<lhs.bitWidth`. The
  /// shift is performed using this masked value.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the shift amount requires no masking.
  ///
  ///     var x: UInt8 = 30                 // 0b00011110
  ///     x &>>= 2
  ///     // x == 7                         // 0b00000111
  ///
  /// However, if you use `19` as `rhs`, the operation first bitmasks `rhs` to
  /// `3`, and then uses that masked value as the number of bits to shift `lhs`.
  ///
  ///     var y: UInt8 = 30                 // 0b00011110
  ///     y &>>= 19
  ///     // y == 3                         // 0b00000011
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the right. If `rhs` is
  ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
  ///     value within that range.
""",
        '&<<': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the left, masking the shift amount to the
  /// type's bit width, and stores the result in the left-hand-side variable.
  ///
  /// The `&<<=` operator performs a *masking shift*, where the value used as
  /// `rhs` is masked to produce a value in the range `0..<lhs.bitWidth`. The
  /// shift is performed using this masked value.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the shift amount requires no masking.
  ///
  ///     var x: UInt8 = 30                 // 0b00011110
  ///     x &<<= 2
  ///     // x == 120                       // 0b01111000
  ///
  /// However, if you pass `19` as `rhs`, the method first bitmasks `rhs` to
  /// `3`, and then uses that masked value as the number of bits to shift `lhs`.
  ///
  ///     var y: UInt8 = 30                 // 0b00011110
  ///     y &<<= 19
  ///     // y == 240                       // 0b11110000
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the left. If `rhs` is
  ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
  ///     value within that range.
""",
        '>>': """\
  /// Stores the result of shifting a value's binary representation the
  /// specified number of digits to the right in the left-hand-side variable.
  ///
  /// The `>>=` operator performs a *smart shift*, which defines a result for a
  /// shift of any value.
  ///
  /// - Using a negative value for `rhs` performs a left shift using
  ///   `abs(rhs)`.
  /// - Using a value for `rhs` that is greater than or equal to the bit width
  ///   of `lhs` is an *overshift*. An overshift results in `-1` for a
  ///   negative value of `lhs` or `0` for a nonnegative value.
  /// - Using any other value for `rhs` performs a right shift on `lhs` by that
  ///   amount.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the value is shifted right by two bits.
  ///
  ///     var x: UInt8 = 30                 // 0b00011110
  ///     x >>= 2
  ///     // x == 7                         // 0b00000111
  ///
  /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits
  /// are set to zero.
  ///
  ///     var y: UInt8 = 30                 // 0b00011110
  ///     y >>= 11
  ///     // y == 0                         // 0b00000000
  ///
  /// Using a negative value as `rhs` is the same as performing a left shift
  /// using `abs(rhs)`.
  ///
  ///     var a: UInt8 = 30                 // 0b00011110
  ///     a >>= -3
  ///     // a == 240                       // 0b11110000
  ///
  ///     var b: UInt8 = 30                 // 0b00011110
  ///     b <<= 3
  ///     // b == 240                       // 0b11110000
  ///
  /// Right shift operations on negative values "fill in" the high bits with
  /// ones instead of zeros.
  ///
  ///     var q: Int8 = -30                 // 0b11100010
  ///     q >>= 2
  ///     // q == -8                        // 0b11111000
  ///
  ///     var r: Int8 = -30                 // 0b11100010
  ///     r >>= 11
  ///     // r == -1                        // 0b11111111
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the right.
""",
        '<<': """\
  /// Stores the result of shifting a value's binary representation the
  /// specified number of digits to the left in the left-hand-side variable.
  ///
  /// The `<<` operator performs a *smart shift*, which defines a result for a
  /// shift of any value.
  ///
  /// - Using a negative value for `rhs` performs a right shift using
  ///   `abs(rhs)`.
  /// - Using a value for `rhs` that is greater than or equal to the bit width
  ///   of `lhs` is an *overshift*, resulting in zero.
  /// - Using any other value for `rhs` performs a left shift on `lhs` by that
  ///   amount.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the value is shifted left by two bits.
  ///
  ///     var x: UInt8 = 30                 // 0b00011110
  ///     x <<= 2
  ///     // x == 120                       // 0b01111000
  ///
  /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits
  /// are set to zero.
  ///
  ///     var y: UInt8 = 30                 // 0b00011110
  ///     y <<= 11
  ///     // y == 0                         // 0b00000000
  ///
  /// Using a negative value as `rhs` is the same as performing a right shift
  /// with `abs(rhs)`.
  ///
  ///     var a: UInt8 = 30                 // 0b00011110
  ///     a <<= -3
  ///     // a == 3                         // 0b00000011
  ///
  ///     var b: UInt8 = 30                 // 0b00011110
  ///     b >>= 3
  ///     // b == 3                         // 0b00000011
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the left.
""",
  }
    return comments[operator]

# documentation for overflow-calculating arithmetic methods, indexed
# by the related operator:
#     +   addingReportingOverflow(_:)
#     -   subtractingReportingOverflow(_:)
#     *   multiplyingReportingOverflow(_:)
#     /   dividedReportingOverflow(by:)
#     %   remainderReportingOverflow(dividingBy:)
def overflowOperationComment(operator):
    comments = {
        '+': """\
  /// Returns the sum of this value and the given value along with a flag
  /// indicating whether overflow occurred in the operation.
  ///
  /// - Parameter rhs: The value to add to this value.
  /// - Returns: A tuple containing the result of the addition along with a
  ///   flag indicating whether overflow occurred. If the `overflow` component
  ///   is `.none`, the `partialValue` component contains the entire sum. If
  ///   the `overflow` component is `.overflow`, an overflow occurred and the
  ///   `partialValue` component contains the truncated sum of this value and
  ///   `rhs`.
""",
        '-': """\
  /// Returns the difference of this value and the given value along with a
  /// flag indicating whether overflow occurred in the operation.
  ///
  /// - Parameter rhs: The value to subtract from this value.
  /// - Returns: A tuple containing the result of the subtraction along with a
  ///   flag indicating whether overflow occurred. If the `overflow` component
  ///   is `.none`, the `partialValue` component contains the entire
  ///   difference. If the `overflow` component is `.overflow`, an overflow
  ///   occurred and the `partialValue` component contains the truncated
  ///   result of `rhs` subtracted from this value.
""",
        '*': """\
  /// Returns the product of this value and the given value along with a flag
  /// indicating whether overflow occurred in the operation.
  ///
  /// - Parameter rhs: The value to multiply by this value.
  /// - Returns: A tuple containing the result of the multiplication along with
  ///   a flag indicating whether overflow occurred. If the `overflow`
  ///   component is `.none`, the `partialValue` component contains the entire
  ///   product. If the `overflow` component is `.overflow`, an overflow
  ///   occurred and the `partialValue` component contains the truncated
  ///   product of this value and `rhs`.
""",
        '/': """\
  /// Returns the quotient of dividing this value by the given value along with
  /// a flag indicating whether overflow occurred in the operation.
  ///
  /// Dividing by zero is not an error when using this method. For a value `x`,
  /// the result of `x.dividedReportingOverflow(by: 0)` is `(x, .overflow)`.
  ///
  /// - Parameter rhs: The value to divide this value by.
  /// - Returns: A tuple containing the result of the division along with a
  ///   flag indicating whether overflow occurred. If the `overflow` component
  ///   is `.none`, the `partialValue` component contains the entire quotient.
  ///   If the `overflow` component is `.overflow`, an overflow occurred and
  ///   the `partialValue` component contains the truncated quotient.
""",
        '%': """\
  // FIXME(integers): the comment is for division instead of remainder
  /// Returns the remainder of dividing this value by the given value along with
  /// a flag indicating whether overflow occurred in the operation.
  ///
  /// Dividing by zero is not an error when using this method. For a value `x`,
  /// the result of `x.dividedReportingOverflow(by: 0)` is `(x, .overflow)`.
  ///
  /// - Parameter rhs: The value to divide this value by.
  /// - Returns: A tuple containing the result of the division along with a
  ///   flag indicating whether overflow occurred. If the `overflow` component
  ///   is `.none`, the `partialValue` component contains the entire quotient.
  ///   If the `overflow` component is `.overflow`, an overflow occurred and
  ///   the `partialValue` component contains the truncated quotient.
""",
    }
    return comments[operator]

# documentation for "unsafe" arithmetic methods, indexed by the related
# operator:
#     +   unsafeAdding(_:)
#     -   unsafeSubtracting(_:)
#     *   unsafeMultiplying(_:)
#     /   unsafeDividing(by:)
def unsafeOperationComment(operator):
    comments = {
        '+': """\
  /// Returns the sum of this value and the given value without checking for
  /// arithmetic overflow.
  ///
  /// If an arithmetic overflow occurs, the behavior is undefined. Use this
  /// function only to avoid the cost of overflow checking when you are sure
  /// that the operation won't overflow.
  ///
  /// - Parameter rhs: The value to add to this value.
  /// - Returns: The sum of this value and `rhs`.
""",
        '-': """\
  /// Returns the difference of this value and the given value without checking
  /// for arithmetic overflow.
  ///
  /// If an arithmetic overflow occurs, the behavior is undefined. Use this
  /// function only to avoid the cost of overflow checking when you are sure
  /// that the operation won't overflow.
  ///
  /// - Parameter rhs: The value to subtract from this value.
  /// - Returns: The difference of this value and `rhs`.
""",
        '*': """\
  /// Returns the product of this value and the given value without checking
  /// for arithmetic overflow.
  ///
  /// If an arithmetic overflow occurs, the behavior is undefined. Use this
  /// function only to avoid the cost of overflow checking when you are sure
  /// that the operation won't overflow.
  ///
  /// - Parameter rhs: The value to multiply by this value.
  /// - Returns: The difference of this value and `rhs`.
""",
        '/': """\
  /// Returns the quotient of dividing this value by the given value without
  /// checking for arithmetic overflow.
  ///
  /// If an arithmetic overflow occurs, the behavior is undefined. Use this
  /// function only to avoid the cost of overflow checking when you are sure
  /// that the operation won't overflow.
  ///
  /// - Parameter rhs: The value to divide this value by.
  /// - Returns: The quotient of dividing this value by `rhs`.
""",
    }
    return comments[operator]

}%

//===----------------------------------------------------------------------===//
//===--- Numeric ----------------------------------------------------------===//
//===----------------------------------------------------------------------===//

/// Declares methods backing binary arithmetic operators--such as `+`, `-` and
/// `*`--and their mutating counterparts.
///
/// The `Numeric` protocol provides a suitable basis for arithmetic on
/// scalar values, such as integers and floating-point numbers. You can write
/// generic methods that operate on any numeric type in the standard library
/// by using the `Numeric` protocol as a generic constraint.
///
/// The following example declares a method that calculates the total of any
/// sequence with `Numeric` elements.
///
///     extension Sequence where Element: Numeric {
///         func sum() -> Element {
///             return reduce(0, +)
///         }
///     }
///
/// The `sum()` method is now available on any sequence or collection with
/// numeric values, whether it is an array of `Double` or a countable range of
/// `Int`.
///
///     let arraySum = [1.1, 2.2, 3.3, 4.4, 5.5].sum()
///     // arraySum == 16.5
///
///     let rangeSum = (1..<10).sum()
///     // rangeSum == 45
///
/// Conforming to the Numeric Protocol
/// =====================================
///
/// To add `Numeric` protocol conformance to your own custom type, implement
/// the required mutating methods. Extensions to `Numeric` provide default
/// implementations for the protocol's nonmutating methods based on the
/// mutating variants.
public protocol Numeric : Equatable, ExpressibleByIntegerLiteral {
  /// Creates a new instance from the given integer, if it can be represented
  /// exactly.
  ///
  /// If the value passed as `source` is not representable exactly, the result
  /// is `nil`. In the following example, the constant `x` is successfully
  /// created from a value of `100`, while the attempt to initialize the
  /// constant `y` from `1_000` fails because the `Int8` type can represent
  /// `127` at maximum:
  ///
  ///     let x = Int8(exactly: 100)
  ///     // x == Optional(100)
  ///     let y = Int8(exactly: 1_000)
  ///     // y == nil
  ///
  /// - Parameter source: A value to convert to this type of integer.
  init?<T : BinaryInteger>(exactly source: T)

  // FIXME(ABI)#44 (Recursive Protocol Constraints): should be just
  // Numeric, Comparable
  /// A type that can represent the absolute value of any possible value of the
  /// conforming type.
  associatedtype Magnitude : Comparable, ExpressibleByIntegerLiteral

  /// The magnitude of this value.
  ///
  /// For any numeric value `x`, `x.magnitude` is the absolute value of `x`.
  /// You can use the `magnitude` property in operations that are simpler to
  /// implement in terms of unsigned values, such as printing the value of an
  /// integer, which is just printing a '-' character in front of an absolute
  /// value.
  ///
  ///     let x = -200
  ///     // x.magnitude == 200
  ///
  /// The global `abs(_:)` function provides more familiar syntax when you need
  /// to find an absolute value. In addition, because `abs(_:)` always returns
  /// a value of the same type, even in a generic context, using the function
  /// instead of the `magnitude` property is encouraged.
  var magnitude: Magnitude { get }

% for x in binaryArithmetic['Numeric']:
  // defaulted using an in-place counterpart, but can be used as an
  // optimization hook
${operatorComment(x.operator, False)}
  static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self

  // implementation hook
${assignmentOperatorComment(x.operator, False)}
  static func ${x.operator}=(_ lhs: inout Self, rhs: Self)
% end
}

% # FIXME(integers): uncomment once the compilation time improves.
% # Don't forget to remove similar definitions from concrete integer types,
% # floating point types, CGFloat, and Decimal in Foundation.
% for Protocol in []: # !!! FIXME !!! ['Numeric', 'BinaryInteger', 'FloatingPoint']:
% # Explicitly providing these operations for BinaryInteger and FloatingPoint
% # protocols because Strideable conformance creates ambiguity if the
% # operations are only defined for Numeric
extension ${Protocol} {
%   if Protocol in ['Numeric', 'FloatingPoint']:
%       ops = binaryArithmetic['Numeric']
%   else:
%       ops = binaryArithmetic['Numeric'] + binaryArithmetic['BinaryInteger']
%   for x in ops:
%     callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
${operatorComment(x.operator, False)}
  @_transparent
  public static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self {
    var lhs = lhs
    lhs ${x.operator}= rhs
    return lhs
  }
%   end
}
% end

/// A type that can represent both positive and negative values.
///
/// The `SignedNumeric` protocol extends the operations defined by the
/// `Numeric` protocol to include a value's additive inverse.
///
/// Conforming to the SignedNumeric Protocol
/// ===========================================
///
/// Because the `SignedNumeric` protocol provides default implementations of
/// both of its required methods, you don't need to do anything beyond
/// declaring conformance to the protocol and ensuring that the values of your
/// type support negation. To customize your type's implementation, provide
/// your own mutating `negate()` method.
public protocol SignedNumeric : Numeric {
  /// Returns the additive inverse of the specified value.
  ///
  /// The negation operator (prefix `-`) returns the additive inverse of its
  /// argument.
  ///
  ///     let x = 21
  ///     let y = -x
  ///     // y == -21
  ///
  /// The resulting value must be representable in the same type as the
  /// argument. In particular, negating a signed, fixed-width integer type's
  /// minimum results in a value that cannot be represented.
  ///
  ///     let z = -Int8.min
  ///     // Overflow error
  ///
  /// - Returns: The additive inverse of this value.
  static prefix func - (_ operand: Self) -> Self

  /// Replaces this value with its additive inverse.
  ///
  /// The following example uses the `negate()` method to negate the value of
  /// an integer `x`:
  ///
  ///     var x = 21
  ///     x.negate()
  ///     // x == -21
  mutating func negate()
}

extension SignedNumeric {
  @_transparent
  public static prefix func - (_ operand: Self) -> Self {
    var result = operand
    result.negate()
    return result
  }

  @_transparent
  public mutating func negate() {
    self = 0 - self
  }
}


/// Returns the absolute value of the given number.
///
/// - Parameter x: A signed number.
/// - Returns: The absolute value of `x`.
@_transparent
public func abs<T : SignedNumeric>(_ x: T) -> T
  where T.Magnitude == T {
  return x.magnitude
}

/// Returns the absolute value of the given number.
///
/// The absolute value of `x` must be representable in the same type. In
/// particular, the absolute value of a signed, fixed-width integer type's
/// minimum cannot be represented.
///
///     let x = Int8.min
///     // x == -128
///     let y = abs(x)
///     // Overflow error
///
/// - Parameter x: A signed number.
/// - Returns: The absolute value of `x`.
public func abs<T : SignedNumeric & Comparable>(_ x: T) -> T {
  return x < 0 ? -x : x
}

extension Numeric {
  @_transparent
  public static prefix func + (x: Self) -> Self {
    return x
  }
}

//===----------------------------------------------------------------------===//
//===--- BinaryInteger ----------------------------------------------------===//
//===----------------------------------------------------------------------===//

/// An integer type with a binary representation.
///
/// The `BinaryInteger` protocol is the basis for all the integer types
/// provided by the standard library. All of the standard library's integer
/// types, such as `Int` and `UInt32`, conform to `BinaryInteger`.
///
/// Converting Between Numeric Types
/// ================================
///
/// You can create new instances of a type that conforms to the `BinaryInteger`
/// protocol from a floating-point number or another binary integer of any
/// type. The `BinaryInteger` protocol provides initializers for four
/// different kinds of conversion.
///
/// Range-Checked Conversion
/// ------------------------
///
/// You use the default `init(_:)` initializer to create a new instance when
/// you're sure that the value passed is representable in the new type. For
/// example, an instance of `Int16` can represent the value `500`, so the
/// first conversion in the code sample below succeeds. That same value is too
/// large to represent as an `Int8` instance, so the second conversion fails,
/// triggering a runtime error.
///
///     let x: Int = 500
///     let y = Int16(x)
///     // y == 500
///
///     let z = Int8(x)
///     // Error: Not enough bits to represent...
///
/// When you create a binary integer from a floating-point value using the
/// default initializer, the value is rounded toward zero before the range is
/// checked. In the following example, the value `127.75` is rounded to `127`,
/// which is representable by the `Int8` type.  `128.25` is rounded to `128`,
/// which is not representable as an `Int8` instance, triggering a runtime
/// error.
///
///     let e = Int8(127.75)
///     // e == 127
///
///     let f = Int8(128.25)
///     // Error: Double value cannot be converted...
///
///
/// Exact Conversion
/// ----------------
///
/// Use the `init?(exactly:)` initializer to create a new instance after
/// checking whether the passed value is representable. Instead of trapping on
/// out-of-range values, using the failable `exact` initializer results in
/// `nil`.
///
///     let x = Int16(exactly: 500)
///     // x == Optional(500)
///
///     let y = Int8(exactly: 500)
///     // y == nil
///
/// When converting floating-point values, the `init?(exact:)` initializer
/// checks both that the passed value has no fractional part and that the
/// value is representable in the resulting type.
///
///     let e = Int8(exactly: 23.0)       // integral value, representable
///     // e == Optional(23)
///
///     let f = Int8(exactly: 23.75)      // fractional value, representable
///     // f == nil
///
///     let g = Int8(exactly: 500.0)      // integral value, nonrepresentable
///     // g == nil
///
/// Clamping Conversion
/// -------------------
///
/// Use the `init(clamping:)` initializer to create a new instance of a binary
/// integer type where out-of-range values are clamped to the representable
/// range of the type. For a type `T`, the resulting value is in the range
/// `T.min...T.max`.
///
///     let x = Int16(clamping: 500)
///     // x == 500
///
///     let y = Int8(clamping: 500)
///     // y == 127
///
///     let z = UInt8(clamping: -500)
///     // z == 0
///
/// Bit Pattern Conversion
/// ----------------------
///
/// Use the `init(extendingOrTruncating:)` initializer to create a new instance
/// with the same bit pattern as the passed value, extending or truncating the
/// value's representation as necessary. Note that the value may not be
/// preserved, particularly when converting between signed to unsigned integer
/// types or when the destination type has a smaller bit width than the source
/// type. The following example shows how extending and truncating work for
/// nonnegative integers:
///
///     let q: Int16 = 850
///     // q == 0b00000011_01010010
///
///     let r = Int8(extendingOrTruncating: q)      // truncate 'q' to fit in 8 bits
///     // r == 82
///     //   == 0b01010010
///
///     let s = Int16(extendingOrTruncating: s)     // extend 'r' to fill 16 bits
///     // s == 82
///     //   == 0b00000000_01010010
///
/// Any padding is performed by *sign-extending* the passed value. When
/// nonnegative integers are extended, the result is padded with zeroes. When
/// negative integers are extended, the result is padded with ones. This
/// example shows several extending conversions of a negative value---note
/// that negative values are sign-extended even when converting to an unsigned
/// type.
///
///     let t: Int8 = -100
///     // t == -100
///     // t's binary representation == 0b10011100
///
///     let u = UInt8(extendingOrTruncating: t)
///     // u == 156
///     // u's binary representation == 0b10011100
///
///     let v = Int16(extendingOrTruncating: t)
///     // v == -100
///     // v's binary representation == 0b11111111_10011100
///
///     let w = UInt16(extendingOrTruncating: t)
///     // w == 65436
///     // w's binary representation == 0b11111111_10011100
///
///
/// Comparing Across Integer Types
/// ==============================
///
/// You can use relational operators, such as the less-than and equal-to
/// operators (`<` and `==`), to compare instances of different binary integer
/// types. The following example compares instances of the `Int`, `UInt`, and
/// `UInt8` types:
///
///     let x: Int = -23
///     let y: UInt = 1_000
///     let z: UInt8 = 23
///
///     if x < y {
///         print("\(x) is less than \(y).")
///     }
///     // Prints "-23 is less than 1000."
///
///     if z > x {
///         print("\(z) is greater than \(x).")
///     }
///     // Prints "23 is greater than -23."
public protocol BinaryInteger :
  Hashable, Numeric, CustomStringConvertible, Strideable
  where Magnitude : BinaryInteger, Magnitude.Magnitude == Magnitude
{
  /// A Boolean value indicating whether this type is a signed integer type.
  ///
  /// *Signed* integer types can represent both positive and negative values.
  /// *Unsigned* integer types can represent only nonnegative values.
  static var isSigned: Bool { get }

  /// Creates an integer from the given floating-point value, if it can be
  /// represented exactly.
  ///
  /// If the value passed as `source` is not representable exactly, the result
  /// is `nil`. In the following example, the constant `x` is successfully
  /// created from a value of `21.0`, while the attempt to initialize the
  /// constant `y` from `21.5` fails:
  ///
  ///     let x = Int(exactly: 21.0)
  ///     // x == Optional(21)
  ///     let y = Int(exactly: 21.5)
  ///     // y == nil
  ///
  /// - Parameter source: A floating-point value to convert to an integer.
  init?<T : FloatingPoint>(exactly source: T)

  /// Creates an integer from the given floating-point value, rounding toward
  /// zero.
  ///
  ///     let x = Int(21.5)
  ///     // x == 21
  ///     let y = Int(-21.5)
  ///     // y == -21
  ///
  /// If `source` is outside the bounds of this type after rounding toward
  /// zero, a runtime error may occur.
  ///
  ///     let z = UInt(-21.5)
  ///     // Error: ...the result would be less than UInt.min
  ///
  /// - Parameter source: A floating-point value to convert to an integer.
  ///   `source` must be representable in this type after rounding toward zero.
  init<T : FloatingPoint>(_ source: T)

  /// Creates a new instance from the given integer.
  ///
  /// If the value passed as `source` is not representable in this type, a
  /// runtime error may occur.
  ///
  ///     let x = -500 as Int
  ///     let y = Int32(x)
  ///     // y == -500
  ///
  ///     // -500 is not representable as a 'UInt32' instance
  ///     let z = UInt32(x)
  ///     // Error
  ///
  /// - Parameter source: An integer to convert. `source` must be representable
  ///   in this type.
  init<T : BinaryInteger>(_ source: T)

  /// Creates a new instance from the bit pattern of the given instance by
  /// sign-extending or truncating to fit this type.
  ///
  /// When the bit width of `T` (the type of `source`) is equal to or greater
  /// than this type's bit width, the result is the truncated
  /// least-significant bits of `source`. For example, when converting a
  /// 16-bit value to an 8-bit type, only the lower 8 bits of `source` are
  /// used.
  ///
  ///     let p: Int16 = -500
  ///     // 'p' has a binary representation of 11111110_00001100
  ///     let q = Int8(extendingOrTruncating: p)
  ///     // q == 12
  ///     // 'q' has a binary representation of 00001100
  ///
  /// When the bit width of `T` is less than this type's bit width, the result
  /// is *sign-extended* to fill the remaining bits. That is, if `source` is
  /// negative, the result is padded with ones; otherwise, the result is
  /// padded with zeros.
  ///
  ///     let u: Int8 = 21
  ///     // 'u' has a binary representation of 00010101
  ///     let v = Int16(extendingOrTruncating: u)
  ///     // v == 21
  ///     // 'v' has a binary representation of 00000000_00010101
  ///
  ///     let w: Int8 = -21
  ///     // 'w' has a binary representation of 11101011
  ///     let x = Int16(extendingOrTruncating: w)
  ///     // x == -21
  ///     // 'x' has a binary representation of 11111111_11101011
  ///     let y = UInt16(extendingOrTruncating: w)
  ///     // y == 65515
  ///     // 'y' has a binary representation of 11111111_11101011
  ///
  /// - Parameter source: An integer to convert to this type.
  init<T : BinaryInteger>(extendingOrTruncating source: T)

  /// Creates a new instance with the representable value that's closest to the
  /// given integer.
  ///
  /// If the value passed as `source` is greater than the maximum representable
  /// value in this type, the result is the type's `max` value. If `source` is
  /// less than the smallest representable value in this type, the result is
  /// the type's `min` value.
  ///
  /// In this example, `x` is initialized as an `Int8` instance by clamping
  /// `500` to the range `-128...127`, and `y` is initialized as a `UInt`
  /// instance by clamping `-500` to the range `0...UInt.max`.
  ///
  ///     let x = Int8(clamping: 500)
  ///     // x == 127
  ///     // x == Int8.max
  ///
  ///     let y = UInt(clamping: -500)
  ///     // y == 0
  ///
  /// - Parameter source: An integer to convert to this type.
  init<T : BinaryInteger>(clamping source: T)

  /// Returns the n-th word, counting from the least significant to most
  /// significant, of this value's binary representation.
  ///
  /// The `_word(at:)` method returns negative values in two's complement
  /// representation, regardless of a type's underlying implementation. If `n`
  /// is greater than the number of words in this value's current
  /// representation, the result is `0` for positive numbers and `~0` for
  /// negative numbers.
  ///
  /// - Parameter n: The word to return, counting from the least significant to
  ///   most significant. `n` must be greater than or equal to zero.
  /// - Returns: An word-sized, unsigned integer with the bit pattern of the
  ///   n-th word of this value.
  func _word(at n: Int) -> UInt

  // FIXME(integers): add doc comments
  // FIXME: Should be `Words : Collection where Words.Iterator.Element == UInt`
  // See <rdar://problem/31798916> for why it isn't.
  associatedtype Words
  var words: Words { get }

  /// The number of bits in the current binary representation of this value.
  ///
  /// This property is a constant for instances of fixed-width integer
  /// types.
  var bitWidth : Int { get }

  /// The number of trailing zeros in this value's binary representation.
  ///
  /// For example, in a fixed-width integer type with a `bitWidth` value of 8,
  /// the number -8 has three trailing zeros.
  ///
  ///     let x = Int8(bitPattern: 0b1111_1000)
  ///     // x == -8
  ///     // x.trailingZeroBitCount == 3
  var trailingZeroBitCount: Int { get }

% for x in chain(*binaryArithmetic.values()):
  // defaulted using an in-place counterpart, but can be used as an
  // optimization hook
${operatorComment(x.operator, False)}
  static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self

  // implementation hook
${assignmentOperatorComment(x.operator, False)}
  static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self)
% end

  /// Returns the inverse of the bits set in the argument.
  ///
  /// The bitwise NOT operator (`~`) is a prefix operator that returns a value
  /// in which all the bits of its argument are flipped: Bits that are `1` in
  /// the argument are `0` in the result, and bits that are `0` in the argument
  /// are `1` in the result. This is equivalent to the inverse of a set. For
  /// example:
  ///
  ///     let x: UInt8 = 5        // 0b00000101
  ///     let notX = ~x           // 0b11111010
  ///
  /// Performing a bitwise NOT operation on 0 returns a value with every bit
  /// set to `1`.
  ///
  ///     let allOnes = ~UInt8.min   // 0b11111111
  ///
  /// - Complexity: O(1).
  static prefix func ~ (_ x: Self) -> Self

% for x in binaryBitwise + maskingShifts:
${operatorComment(x.operator, False)}
  static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self

${assignmentOperatorComment(x.operator, False)}
  static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self)
% end

  /// Returns the quotient and remainder of this value divided by the given
  /// value.
  ///
  /// Use this method to calculate the quotient and remainder of a division at
  /// the same time.
  ///
  ///     let x = 1_000_000
  ///     let (q, r) = x.quotientAndRemainder(dividingBy: 933)
  ///     // q == 1071
  ///     // r == 757
  ///
  /// - Parameter rhs: The value to divide this value by.
  /// - Returns: A tuple containing the quotient and remainder of this value
  ///   divided by `rhs`.
  func quotientAndRemainder(dividingBy rhs: Self)
    -> (quotient: Self, remainder: Self)

  /// Returns `-1` if this value is negative and `1` if it's positive;
  /// otherwise, `0`.
  ///
  /// - Returns: The sign of this number, expressed as an integer of the same
  ///   type.
  func signum() -> Self
}

extension BinaryInteger {
  @_transparent
  public init() {
    self = 0
  }

  public init?<T : FloatingPoint>(exactly source: T) {
    // FIXME(integers): implement
    fatalError()
  }

  @_transparent
  public func signum() -> Self {
    return (self > (0 as Self) ? 1 : 0) - (self < (0 as Self) ? 1 : 0)
  }

  /// The number of words used for the current binary representation of this
  /// value.
  ///
  /// This property is a constant for instances of fixed-width integer types.
  @_transparent
  public var _countRepresentedWords: Int {
    return (self.bitWidth + ${word_bits} - 1) / ${word_bits}
  }

  public func quotientAndRemainder(dividingBy rhs: Self)
    -> (quotient: Self, remainder: Self) {
    return (self / rhs, self % rhs)
  }

  % for x in binaryBitwise + maskingShifts:

${operatorComment(x.operator, False)}
  @_transparent
  public static func ${x.operator} (lhs: Self, rhs: Self) -> Self {
    var lhs = lhs
    lhs ${x.operator}= rhs
    return lhs
  }

  % end

  % for x in maskingShifts:

${operatorComment(x.operator, False)}
  public static func ${x.operator} <
    Other : BinaryInteger
  >(lhs: Self, rhs: Other) -> Self {
    return lhs ${x.operator} Self(extendingOrTruncating: rhs)
  }

${assignmentOperatorComment(x.operator, False)}
  @_transparent
  public static func ${x.operator}= <
    Other : BinaryInteger
  >(lhs: inout Self, rhs: Other) {
    lhs = lhs ${x.operator} rhs
  }

  % end
}

// Strideable conformance
extension BinaryInteger {
  // FIXME(ABI): using Int as the return type is wrong.
  @_transparent
  public func distance(to other: Self) -> Int {
    let distance = other - self
    if let result = Int(exactly: distance) {
      return result
    }
    _preconditionFailure("Distance is not representable in Int")
  }

  // FIXME(ABI): using Int as the parameter type is wrong.
  @_transparent
  public func advanced(by n: Int) -> Self {
    var advanced: Int = Int(self)
    advanced += n
    if let result = Self(exactly: advanced) {
      return result
    }
    _preconditionFailure("The result of advanced(by:) is not representable")
  }
}

extension Int {
  // FIXME(ABI): using Int as the return type is wrong.
  @_transparent
  public func distance(to other: Int) -> Int {
    return other - self
  }

  // FIXME(ABI): using Int as the parameter type is wrong.
  @_transparent
  public func advanced(by n: Int) -> Int {
    return self + n
  }
}


//===----------------------------------------------------------------------===//
//===--- Heterogeneous comparison -----------------------------------------===//
//===----------------------------------------------------------------------===//

extension BinaryInteger {
  /// Returns a Boolean value indicating whether the two given values are
  /// equal.
  ///
  /// You can check the equality of instances of any `BinaryInteger` types
  /// using the equal-to operator (`==`). For example, you can test whether
  /// the first `UInt8` value in a string's UTF-8 encoding is equal to the
  /// first `UInt32` value in its Unicode scalar view:
  ///
  ///     let gameName = "Red Light, Green Light"
  ///     if let firstUTF8 = gameName.utf8.first,
  ///         let firstScalar = gameName.unicodeScalars.first?.value {
  ///         print("First code values are equal: \(firstUTF8 == firstScalar)")
  ///     }
  ///     // Prints "First code values are equal: true"
  ///
  /// - Parameters:
  ///   - lhs: An integer to compare.
  ///   - rhs: Another integer to compare.
  @inline(__always)
  public static func == <
    Other : BinaryInteger
  >(lhs: Self, rhs: Other) -> Bool {
    let lhsNegative = Self.isSigned && lhs < (0 as Self)
    let rhsNegative = Other.isSigned && rhs < (0 as Other)

    if lhsNegative != rhsNegative { return false }

    // Here we know the values are of the same sign.
    //
    // There are a few possible scenarios from here:
    //
    // 1. Both values are negative
    //  - If one value is strictly wider than the other, then it is safe to
    //    convert to the wider type.
    //  - If the values are of the same width, it does not matter which type we
    //    choose to convert to as the values are already negative, and thus
    //    include the sign bit if two's complement representation already.
    // 2. Both values are non-negative
    //  - If one value is strictly wider than the other, then it is safe to
    //    convert to the wider type.
    //  - If the values are of the same width, than signedness matters, as not
    //    unsigned types are 'wider' in a sense they don't need to 'waste' the
    //    sign bit. Therefore it is safe to convert to the unsigned type.

    if lhs.bitWidth < rhs.bitWidth {
      return Other(extendingOrTruncating: lhs) == rhs
    }
    if lhs.bitWidth > rhs.bitWidth {
      return lhs == Self(extendingOrTruncating: rhs)
    }

    if Self.isSigned {
      return Other(extendingOrTruncating: lhs) == rhs
    }
    return lhs == Self(extendingOrTruncating: rhs)
  }

  /// Returns a Boolean value indicating whether the two given values are not
  /// equal.
  ///
  /// You can check the inequality of instances of any `BinaryInteger` types
  /// using the not-equal-to operator (`!=`). For example, you can test
  /// whether the first `UInt8` value in a string's UTF-8 encoding is not
  /// equal to the first `UInt32` value in its Unicode scalar view:
  ///
  ///     let gameName = "Red Light, Green Light"
  ///     if let firstUTF8 = gameName.utf8.first,
  ///         let firstScalar = gameName.unicodeScalars.first?.value {
  ///         print("First code values are different: \(firstUTF8 != firstScalar)")
  ///     }
  ///     // Prints "First code values are different: false"
  ///
  /// - Parameters:
  ///   - lhs: An integer to compare.
  ///   - rhs: Another integer to compare.
  @_transparent
  public static func != <
    Other : BinaryInteger
  >(lhs: Self, rhs: Other) -> Bool {
    return !(lhs == rhs)
  }

  /// Returns a Boolean value indicating whether the value of the first
  /// argument is less than that of the second argument.
  ///
  /// You can compare instances of any `BinaryInteger` types using the
  /// less-than operator (`<`), even if the two instances are of different
  /// types.
  ///
  /// - Parameters:
  ///   - lhs: An integer to compare.
  ///   - rhs: Another integer to compare.
  @inline(__always)
  public static func < <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool {
    let lhsNegative = Self.isSigned && lhs < (0 as Self)
    let rhsNegative = Other.isSigned && rhs < (0 as Other)
    if lhsNegative != rhsNegative { return lhsNegative }

    if lhs == (0 as Self) && rhs == (0 as Other) { return false }

    // if we get here, lhs and rhs have the same sign. If they're negative,
    // then Self and Other are both signed types, and one of them can represent
    // values of the other type. Otherwise, lhs and rhs are positive, and one
    // of Self, Other may be signed and the other unsigned.

    let rhsAsSelf = Self(extendingOrTruncating: rhs)
    let rhsAsSelfNegative = rhsAsSelf < (0 as Self)


    // Can we round-trip rhs through Other?
    if Other(extendingOrTruncating: rhsAsSelf) == rhs &&
      // This additional check covers the `Int8.max < (128 as UInt8)` case.
      // Since the types are of the same width, init(extendingOrTruncating:)
      // will result in a simple bitcast, so that rhsAsSelf would be -128, and
      // `lhs < rhsAsSelf` will return false.
      // We basically guard against that bitcast by requiring rhs and rhsAsSelf
      // to be the same sign.
      rhsNegative == rhsAsSelfNegative {
      return lhs < rhsAsSelf
    }

    return Other(extendingOrTruncating: lhs) < rhs
  }

  /// Returns a Boolean value indicating whether the value of the first
  /// argument is less than or equal to that of the second argument.
  ///
  /// You can compare instances of any `BinaryInteger` types using the
  /// less-than-or-equal-to operator (`<=`), even if the two instances are of
  /// different types.
  ///
  /// - Parameters:
  ///   - lhs: An integer to compare.
  ///   - rhs: Another integer to compare.
  @_transparent
  //@inline(__always)
  public static func <= <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool {
    return !(rhs < lhs)
  }

  /// Returns a Boolean value indicating whether the value of the first
  /// argument is greater than or equal to that of the second argument.
  ///
  /// You can compare instances of any `BinaryInteger` types using the
  /// greater-than-or-equal-to operator (`>=`), even if the two instances are
  /// of different types.
  ///
  /// - Parameters:
  ///   - lhs: An integer to compare.
  ///   - rhs: Another integer to compare.
  @_transparent
  //@inline(__always)
  public static func >= <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool {
    return !(lhs < rhs)
  }

  /// Returns a Boolean value indicating whether the value of the first
  /// argument is greater than that of the second argument.
  ///
  /// You can compare instances of any `BinaryInteger` types using the
  /// greater-than operator (`>`), even if the two instances are of different
  /// types.
  ///
  /// - Parameters:
  ///   - lhs: An integer to compare.
  ///   - rhs: Another integer to compare.
  @_transparent
  //@inline(__always)
  public static func > <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool {
    return rhs < lhs
  }
}

//===----------------------------------------------------------------------===//
//===--- Ambiguity breakers -----------------------------------------------===//
// These two versions of the operators are not ordered with respect to one
// another, but the compiler choses the second one, and that results in infinite
// recursion.
//
//     <T : Comparable>(T, T) -> Bool
//     <T : BinaryInteger, U : BinaryInteger>(T, U) -> Bool
//
// so we define:
//
//     <T : BinaryInteger>(T, T) -> Bool
//
//===----------------------------------------------------------------------===//

extension BinaryInteger {
  @_transparent
  public static func != (lhs: Self, rhs: Self) -> Bool {
    return !(lhs == rhs)
  }

  @inline(__always)
  public static func <= (lhs: Self, rhs: Self) -> Bool {
    return !(rhs < lhs)
  }

  @inline(__always)
  public static func >= (lhs: Self, rhs: Self) -> Bool {
    return !(lhs < rhs)
  }

  @inline(__always)
  public static func > (lhs: Self, rhs: Self) -> Bool {
    return rhs < lhs
  }
}

//===----------------------------------------------------------------------===//
//===--- BinaryInteger smart shifts ---------------------------------------===//
//===----------------------------------------------------------------------===//
// FIXME(integers): uncomment once <rdar://problem/29643515> gets fixed
#if false
extension BinaryInteger {
%   for x in maskingShifts:
  @_transparent
  public static func ${x.nonMaskingOperator} <
    Other : BinaryInteger
  >(lhs: Self, rhs: Other) -> Self {
    var lhs = lhs
    lhs ${x.nonMaskingOperator}= rhs
    return lhs
  }

  // It is hard to imagine overshift to the left in an arbitrarily sized
  // integer, but shifting too far to the right and negative shift cases are
  // supported.
%     reversedOperator = x.operator.translate(maketrans('<>', '><'))
%     isRightShift = '>' in x.operator
  @_transparent
  public static func ${x.nonMaskingOperator}= <
    Other : BinaryInteger
  >(lhs: inout Self, rhs: Other) {
    if rhs < (0 as Other) {
      lhs ${reversedOperator}= (0 - rhs)
      return
    }
%     if isRightShift:
    let overshift = Self.isSigned
      ? (lhs < (0 as Self) ? ~(0 as Self) : 0 )
      : 0
    if rhs >= lhs.bitWidth {
      lhs = overshift
      return
    }
%     end
    lhs ${x.operator}= Self(extendingOrTruncating: rhs)
  }
%   end
}
#endif

extension BinaryInteger {
  // FIXME(integers): Should be removed once words get implemented properly.
  // Meanhile it allows to conform to the BinaryInteger without implementing
  // underscored APIs. https://bugs.swift.org/browse/SR-5275
  public func _word(at n: Int) -> UInt {
    fatalError("Should be overridden")
  }

  // FIXME(integers): inefficient. Should get rid of _word(at:) and
  // _countRepresentedWords, and make `words` the basic operation.
  public var words: [UInt] {
    var result = [UInt]()
    result.reserveCapacity(_countRepresentedWords)
    for i in 0..<self._countRepresentedWords {
      result.append(_word(at: i))
    }
    return result
  }
}

//===----------------------------------------------------------------------===//
//===--- FixedWidthInteger ------------------------------------------------===//
//===----------------------------------------------------------------------===//

/// An indicator of whether an arithmetic operation overflowed.
///
/// Some arithmetic operations on fixed-width integers return an
/// `ArithmeticOverflow` instance to indicate whether an overflow has
/// occurred. For example, adding `UInt8.max` to itself results in a value that
/// can't be represented by an `UInt8` instance without overflowing.
///
///     let x = UInt8.max
///     // x == 255
///     let (y, overflow) = x.addingReportingOverflow(x)
///     // y == 254
///     // overflow == ArithmeticOverflow.overflow
@_fixed_layout
public enum ArithmeticOverflow {
  @_transparent
  public init(_ overflow: Bool) { self = overflow ? .overflow : .none }
  /// An indication that no overflow occurred in the operation.
  case none
  /// An indication that an overflow did occur in the operation.
  case overflow
}

/// An integer type that uses a fixed size for every instance.
///
/// The `FixedWidthInteger` protocol adds binary bitwise operations, bit
/// shifts, and overflow handling to the operations supported by the
/// `BinaryInteger` protocol.
///
/// Use the `FixedWidthInteger` protocol as a constraint or extension point
/// when writing operations that depend on bit shifting, performing bitwise
/// operations, catching overflows, or having access to the maximum or minimum
/// representable value of a type. For example, the following code provides a
/// `binaryString` property on every fixed-width integer that represents the
/// number's binary representation, split into 8-bit chunks.
///
///     extension FixedWidthInteger {
///         var binaryString: String {
///             var result: [String] = []
///             for i in 0..<(Self.bitWidth / 8) {
///                 let byte = UInt8(extendingOrTruncating: self >> (i * 8))
///                 let byteString = String(byte, radix: 2)
///                 let padding = String(repeating: "0",
///                                      count: 8 - byteString.count)
///                 result.append(padding + byteString)
///             }
///             return "0b" + result.reversed().joined(separator: "_")
///         }
///     }
///
///     print(Int16.max.binaryString)
///     // Prints "0b01111111_11111111"
///     print((101 as UInt8).binaryString)
///     // Prints "0b11001001"
///
/// The `binaryString` implementation uses the static `bitWidth` property and
/// the right shift operator (`<<`), both of which are available to any type
/// that conforms to the `FixedWidthInteger` protocol.
///
/// The next example declares the generic `squared` function, which accepts an
/// instance `x` of any fixed-width integer type. The function uses the
/// `multipliedReportingOverflow(by:)` method to multiply `x` by itself and check
/// whether the result is too large to represent in the same type.
///
///     func squared<T: FixedWidthInteger>(_ x: T) -> T? {
///         let (result, overflow) = x.multipliedReportingOverflow(by: x)
///         guard overflow == .none else {
///             return nil
///         }
///         return result
///     }
///
///     let (x, y): (Int8, Int8) = (9, 123)
///     print(squared(x))
///     // Prints "Optional(81)"
///     print(squared(y))
///     // Prints "nil"
///
/// Conforming to the FixedWidthInteger Protocol
/// ============================================
///
/// To make your own custom type conform to the `FixedWidthInteger` protocol,
/// declare the required initializers, properties, and methods. The required
/// methods that are suffixed with `ReportingOverflow` serve as the
/// customization points for arithmetic operations. When you provide just those
/// methods, the standard library provides default implementations for all
/// other arithmetic methods and operators.
public protocol FixedWidthInteger : BinaryInteger, _BitwiseOperations
  where Magnitude : FixedWidthInteger
{
  /// The number of bits used for the underlying binary representation of
  /// values of this type.
  ///
  /// An unsigned, fixed-width integer type can represent values from 0 through
  /// `(2 ** bitWidth) - 1`, where `**` is exponentiation. A signed,
  /// fixed-width integer type can represent values from
  /// `-(2 ** (bitWidth - 1))` through `(2 ** (bitWidth - 1)) - 1`. For example,
  /// the `Int8` type has a `bitWidth` value of 8 and can store any integer in
  /// the range `-128...127`.
  static var bitWidth : Int { get }

  /// The maximum representable integer in this type.
  ///
  /// For unsigned integer types, this value is `(2 ** bitWidth) - 1`, where
  /// `**` is exponentiation. For signed integer types, this value is
  /// `(2 ** (bitWidth - 1)) - 1`.
  static var max: Self { get }

  /// The minimum representable integer in this type.
  ///
  /// For unsigned integer types, this value is always `0`. For signed integer
  /// types, this value is `-(2 ** (bitWidth - 1))`, where `**` is
  /// exponentiation.
  static var min: Self { get }

% for x in binaryArithmetic['Numeric'] + binaryArithmetic['BinaryInteger']:
${overflowOperationComment(x.operator)}
  func ${x.name}ReportingOverflow(
    ${x.firstArg} rhs: Self
  ) -> (partialValue: Self, overflow: ArithmeticOverflow)
% end

  /// Returns a tuple containing the high and low parts of the result of
  /// multiplying its arguments.
  ///
  /// Use this method to calculate the full result of a product that would
  /// otherwise overflow. Unlike traditional truncating multiplication, the
  /// `multipliedFullWidth(by:)` method returns an instance of DoubleWith<Self>,
  /// containing both the `high` and `low` parts of the product of `self` and
  /// `other`. The following example uses this method to multiply two `UInt8`
  /// values that normally overflow when multiplied:
  ///
  ///     let x: UInt8 = 100
  ///     let y: UInt8 = 20
  ///     let result = x.multipliedFullWidth(by: y)
  ///     // result.high == 0b00000111
  ///     // result.low  == 0b11010000
  ///
  /// The product of `x` and `y` is 2000, which is too large to represent in a
  /// `UInt8` instance. The `high` and `low` properties of the `result` value
  /// represent 2000 when concatenated to form a double-width integer; that
  /// is, using `result.high` as the high byte and `result.low` as the low byte
  /// of a `UInt16` instance.
  ///
  ///     let z = UInt16(result.high) << 8 | UInt16(result.low)
  ///     // z == 2000
  ///
  /// - Parameters:
  ///   - other: A value to multiply `self` by.
  /// - Returns: A tuple containing the high and low parts of the result of
  ///   multiplying `self` and `other`.
  // FIXME(integers): figure out how to return DoubleWidth<Self> or correct the
  // doc comment
  func multipliedFullWidth(by other: Self) -> (high: Self, low: Self.Magnitude)

  /// Returns a tuple containing the quotient and remainder of dividing the
  /// first argument by `self`.
  ///
  /// The resulting quotient must be representable within the bounds of the
  /// type. If the quotient of dividing `dividend` by `self` is too large to
  /// represent in the type, a runtime error may occur.
  ///
  /// - Parameters:
  ///   - dividend: A DoubleWidth<Self> value containing the high and low parts
  ///     of a double-width integer. The `high` component of the value carries
  ///     the sign, if the type is signed.
  /// - Returns: A tuple containing the quotient and remainder of `dividend`
  ///   divided by `self`.
  func dividingFullWidth(_ dividend: (high: Self, low: Self.Magnitude))
    -> (quotient: Self, remainder: Self)

  init(_truncatingBits bits: UInt)

  /// The number of bits equal to 1 in this value's binary representation.
  ///
  /// For example, in a fixed-width integer type with a `bitWidth` value of 8,
  /// the number 31 has five bits equal to 1.
  ///
  ///     let x: Int8 = 0b0001_1111
  ///     // x == 31
  ///     // x.nonzeroBitCount == 5
  var nonzeroBitCount: Int { get }

  /// The number of leading zeros in this value's binary representation.
  ///
  /// For example, in a fixed-width integer type with a `bitWidth` value of 8,
  /// the number 31 has three leading zeros.
  ///
  ///     let x: Int8 = 0b0001_1111
  ///     // x == 31
  ///     // x.leadingZeroBitCount == 3
  var leadingZeroBitCount: Int { get }

  /// Creates an integer from its big-endian representation, changing the byte
  /// order if necessary.
  ///
  /// - Parameter value: A value to use as the big-endian representation of the
  ///   new integer.
  init(bigEndian value: Self)

  /// Creates an integer from its little-endian representation, changing the
  /// byte order if necessary.
  ///
  /// - Parameter value: A value to use as the little-endian representation of
  ///   the new integer.
  init(littleEndian value: Self)

  /// The big-endian representation of this integer.
  ///
  /// If necessary, the byte order of this value is reversed from the typical
  /// byte order of this integer type. On a big-endian platform, for any
  /// integer `x`, `x == x.bigEndian`.
  var bigEndian: Self { get }

  /// The little-endian representation of this integer.
  ///
  /// If necessary, the byte order of this value is reversed from the typical
  /// byte order of this integer type. On a little-endian platform, for any
  /// integer `x`, `x == x.littleEndian`.
  var littleEndian: Self { get }

  /// A representation of this integer with the byte order swapped.
  var byteSwapped: Self { get }
}

extension FixedWidthInteger {
  /// The empty bitset.
  ///
  /// The `allZeros` static property is the [identity element][] for bitwise OR
  /// and XOR operations and the [fixed point][] for bitwise AND operations.
  /// For example:
  ///
  ///     let x: UInt8 = 5        // 0b00000101
  ///
  ///     // Identity
  ///     x | .allZeros           // 0b00000101
  ///     x ^ .allZeros           // 0b00000101
  ///
  ///     // Fixed point
  ///     x & .allZeros           // 0b00000000
  ///
  /// [identity element]:http://en.wikipedia.org/wiki/Identity_element
  /// [fixed point]:http://en.wikipedia.org/wiki/Fixed_point_(mathematics)
  @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0")
  public static var allZeros: Self { return 0 }

  @_inlineable
  public var bitWidth: Int { return Self.bitWidth }

  public init(littleEndian value: Self) {
#if _endian(little)
    self = value
#else
    self = value.byteSwapped
#endif
  }
  
  public init(bigEndian value: Self) {
#if _endian(big)
    self = value
#else
    self = value.byteSwapped
#endif
  }
  
  public var littleEndian: Self {
#if _endian(little)
    return self
#else
    return byteSwapped
#endif
  }
  
  public var bigEndian: Self {
#if _endian(big)
    return self
#else
    return byteSwapped
#endif
  }
}

//===----------------------------------------------------------------------===//
//===--- Operators on FixedWidthInteger -----------------------------------===//
//===----------------------------------------------------------------------===//

extension FixedWidthInteger {
  @_transparent
  public static prefix func ~ (x: Self) -> Self {
    return 0 &- x &- 1
  }

  % for x in maskingShifts:

//===----------------------------------------------------------------------===//
//=== "Smart ${x.description}", supporting overshifts and negative shifts -===//
//===----------------------------------------------------------------------===//

${operatorComment(x.nonMaskingOperator, True)}
  @available(swift, introduced: 4)
  @_transparent
  public static func ${x.nonMaskingOperator} <
    Other : BinaryInteger
  >(lhs: Self, rhs: Other) -> Self {
    var lhs = lhs
    ${x.helper}Generic(&lhs, rhs)
    return lhs
  }

// FIXME(integers): uncommenting this overload results in a compiler not being
// able to typecheck expression like `(int64 >> 8) & 0xFF`.
#if false
  @_transparent
  public static func ${x.nonMaskingOperator} (_ lhs: Self, _ rhs: Int) -> Self {
    return ${x.helper}(lhs, rhs)
  }

  @_transparent
  public static func ${x.nonMaskingOperator}= (_ lhs: inout Self, _ rhs: Int) {
    lhs = ${x.helper}(lhs, rhs)
  }
#endif

  @available(swift, introduced: 4)
  @_transparent
  public static func ${x.nonMaskingOperator}= <
    Other : BinaryInteger
  >(lhs: inout Self, rhs: Other) {
    ${x.helper}Generic(&lhs, rhs)
  }

  @_transparent
  public static func ${x.helper}Generic <
    Other : BinaryInteger
  >(_ lhs: inout Self, _ rhs: Other) {
    let shift = rhs < -Self.bitWidth ? -Self.bitWidth
                : rhs > Self.bitWidth ? Self.bitWidth
                : Int(rhs)
    lhs = ${x.helper}(lhs, shift)
  }

%   reversedOperator = x.operator.translate(maketrans('<>', '><'))
%   isRightShift = '>' in x.operator
  @inline(__always)
  public static func ${x.helper}(_ lhs: Self, _ rhs: Int) -> Self {
    let overshiftR = Self.isSigned ? lhs &>> (Self.bitWidth - 1) : 0
    let overshiftL: Self = 0
    if _fastPath(rhs >= 0) {
      if _fastPath(rhs < Self.bitWidth) {
        return lhs ${x.operator} Self(extendingOrTruncating: rhs)
      }
      return overshift${'LR'[isRightShift]}
    }

    if _slowPath(rhs <= -Self.bitWidth) {
      return overshift${'RL'[isRightShift]}
    }
    return lhs ${reversedOperator} -rhs
  }

% end # maskingShifts
}

extension FixedWidthInteger {
  @_semantics("optimize.sil.specialize.generic.partial.never")
  public init<Other: BinaryInteger>(clamping source: Other) {
    if _slowPath(source < Self.min) {
      self = Self.min
    }
    else if _slowPath(source > Self.max) {
      self = Self.max
    }
    else { self = Self(extendingOrTruncating: source) }
  }

% for x in binaryArithmetic['Numeric'] + binaryArithmetic["BinaryInteger"][:1]:
%   callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
// FIXME(integers): pending optimizer work on handling the case where the
// boolean value is wrapped into a two-case enum and then immediately
// unwrapped. <rdar://problem/29004429>
// Uncomment this block and remove the corresponding one from the concrete
// types once the optimizer is ready.
#if false
${assignmentOperatorComment(x.operator, True)}
  @_transparent
  public static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self) {
    let (result, overflow) = lhs.${x.name}ReportingOverflow(${callLabel}rhs)
    _precondition(overflow == .none, "Overflow in ${x.operator}=")
    lhs = result
  }
#endif
// end of FIXME(integers)

${unsafeOperationComment(x.operator)}
  @_transparent
  public func unsafe${capitalize(x.name)}(${x.firstArg} other: Self) -> Self {
    let (result, overflow) = self.${x.name}ReportingOverflow(${callLabel}other)

    if (overflow != .none) {
      if (_isDebugAssertConfiguration()) {
        _preconditionFailure("overflow in unsafe${capitalize(x.name)}")
      }
      else {
        Builtin.conditionallyUnreachable()
      }
    }
    return result
  }
% end

  @inline(__always)
  public init<T : BinaryInteger>(extendingOrTruncating source: T) {
    if Self.bitWidth <= ${word_bits} {
      self = Self.init(_truncatingBits: source._word(at: 0))
    }
    else {
      var result: Self = source < (0 as T) ? ~0 : 0
      // start with the most significant word
      var n = source._countRepresentedWords
      while n >= 0 {
        // masking is OK here because this we have already ensured
        // that Self.bitWidth > ${word_bits}.  Not masking results in
        // infinite recursion.
        result &<<= (${word_bits} as Self)
        result |= Self(_truncatingBits: source._word(at: n))
        n -= 1
      }

      self = result
    }
  }

  @_transparent
  public // transparent
  static var _highBitIndex: Self {
    return Self.init(_truncatingBits: UInt(Self.bitWidth._value) &- 1)
  }

% for x in chain(*binaryArithmetic.values()):
%   callLabel = x.firstArg + ': ' if not x.firstArg == '_' else ''
%   if x.kind != '/':
${operatorComment('&' + x.operator, True)}
  @_transparent
  public static func &${x.operator} (lhs: Self, rhs: Self) -> Self {
    return lhs.${x.name}ReportingOverflow(${callLabel}rhs).partialValue
  }
%   end
% end
}

//===----------------------------------------------------------------------===//
//===--- UnsignedInteger --------------------------------------------------===//
//===----------------------------------------------------------------------===//

/// An integer type that can represent only nonnegative values.
public protocol UnsignedInteger : BinaryInteger { }

extension UnsignedInteger {
  /// The magnitude of this value.
  ///
  /// Every unsigned integer is its own magnitude, so for any value `x`,
  /// `x == x.magnitude`.
  ///
  /// The global `abs(_:)` function provides more familiar syntax when you need
  /// to find an absolute value. In addition, because `abs(_:)` always returns
  /// a value of the same type, even in a generic context, using the function
  /// instead of the `magnitude` property is encouraged.
  @_transparent
  public var magnitude: Self { return self }

  /// A Boolean value indicating whether this type is a signed integer type.
  ///
  /// This property is always `false` for unsigned integer types.
  @_transparent
  public static var isSigned: Bool { return false }

  /// A textual representation of this value.
  public var description: String {
    if self.bitWidth <= ${word_bits} {
      return _uint64ToString(UInt64(extendingOrTruncating: self))
    }
    if self == (0 as Self) {
      return "0"
    }
    return renderNonZeroDescription()
  }

  // FIXME(integers): perhaps a faster implementation is possible
  @_transparent
  internal func renderNonZeroDescription() -> String {
    let ascii0 = 48
    var buf: [Unicode.Scalar] = []

    var x = self
    repeat {
      let r = x % 10
      x /= 10
      buf.append(
        Unicode.Scalar(
          ascii0 + Int(UInt(extendingOrTruncating: r)._value))!)
    }
    while x != (0 as Self)
    return String(buf.reversed().lazy.map { Character($0) })
  }
}

extension UnsignedInteger where Self : FixedWidthInteger {
  @_semantics("optimize.sil.specialize.generic.partial.never")
  @inline(__always)
  public init<T : BinaryInteger>(_ source: T) {
    // This check is potentially removable by the optimizer
    if T.isSigned {
      _precondition(source >= (0 as T), "Negative value is not representable")
    }
    // This check is potentially removable by the optimizer
    if source.bitWidth >= Self.bitWidth {
      _precondition(source <= Self.max,
        "Not enough bits to represent a signed value")
    }
    self.init(extendingOrTruncating: source)
  }

  @_semantics("optimize.sil.specialize.generic.partial.never")
  @inline(__always)
  public init?<T : BinaryInteger>(exactly source: T) {
    // This check is potentially removable by the optimizer
    if T.isSigned && source < (0 as T) {
      return nil
    }
    // The width check can be eliminated by the optimizer
    if source.bitWidth >= Self.bitWidth &&
       source > Self.max {
      return nil
    }
    self.init(extendingOrTruncating: source)
  }

  /// The maximum representable integer in this type.
  ///
  /// For unsigned integer types, this value is `(2 ** bitWidth) - 1`, where
  /// `**` is exponentiation.
  @_transparent
  public static var max: Self {
    return ~0
  }

  /// The minimum representable integer in this type.
  ///
  /// For unsigned integer types, this value is always `0`.
  @_transparent
  public static var min: Self {
    return 0
  }
}


//===----------------------------------------------------------------------===//
//===--- SignedInteger ----------------------------------------------------===//
//===----------------------------------------------------------------------===//

/// An integer type that can represent both positive and negative values.
public protocol SignedInteger : BinaryInteger, SignedNumeric {
  // These requirements are for the source code compatibility with Swift 3
  static func _maskingAdd(_ lhs: Self, _ rhs: Self) -> Self
  static func _maskingSubtract(_ lhs: Self, _ rhs: Self) -> Self
}

extension SignedInteger {
  /// A textual representation of this value.
  public var description: String {
    if self.bitWidth <= ${word_bits} {
      return _int64ToString(Int64(extendingOrTruncating: self))
    }

    let base = magnitude.description
    return self < (0 as Self) ? "-" + base : base
  }

  /// A Boolean value indicating whether this type is a signed integer type.
  ///
  /// This property is always `true` for signed integer types.
  @_transparent
  public static var isSigned: Bool { return true }
}

extension SignedInteger where Self : FixedWidthInteger {
  @_semantics("optimize.sil.specialize.generic.partial.never")
  @inline(__always)
  public init<T : BinaryInteger>(_ source: T) {
    // This check is potentially removable by the optimizer
    if T.isSigned && source.bitWidth > Self.bitWidth {
      _precondition(source >= Self.min,
        "Not enough bits to represent a signed value")
    }
    // This check is potentially removable by the optimizer
    if (source.bitWidth > Self.bitWidth) ||
       (source.bitWidth == Self.bitWidth && !T.isSigned) {
      _precondition(source <= Self.max,
        "Not enough bits to represent a signed value")
    }
    self.init(extendingOrTruncating: source)
  }

  @_semantics("optimize.sil.specialize.generic.partial.never")
  @inline(__always)
  public init?<T : BinaryInteger>(exactly source: T) {
    // This check is potentially removable by the optimizer
    if T.isSigned && source.bitWidth > Self.bitWidth && source < Self.min {
      return nil
    }
    // The width check can be eliminated by the optimizer
    if (source.bitWidth > Self.bitWidth ||
        (source.bitWidth == Self.bitWidth && !T.isSigned)) &&
       source > Self.max {
      return nil
    }
    self.init(extendingOrTruncating: source)
  }

  /// The maximum representable integer in this type.
  ///
  /// For signed integer types, this value is `(2 ** (bitWidth - 1)) - 1`,
  /// where `**` is exponentiation.
  @_transparent
  public static var max: Self {
    return ~min
  }

  /// The minimum representable integer in this type.
  ///
  /// For signed integer types, this value is `-(2 ** (bitWidth - 1))`, where
  /// `**` is exponentiation.
  @_transparent
  public static var min: Self {
    return (-1 as Self) &<< Self._highBitIndex
  }
}


//===----------------------------------------------------------------------===//
//===--- Concrete FixedWidthIntegers --------------------------------------===//
//===----------------------------------------------------------------------===//

% for self_type in all_integer_types(word_bits):
%   bits = self_type.bits
%   signed = self_type.is_signed
%   BuiltinName = self_type.builtin_name
%   Self = self_type.stdlib_name
%   OtherSelf = self_type.get_opposite_signedness().stdlib_name
%   Unsigned = 'Signed' if signed else 'Unsigned'
%   u = 's' if signed else 'u'
%   U = 'U' if signed else ''
%   z = 's' if signed else 'z'

%   Article = 'An' if bits == 8 else 'A'
%   if bits == word_bits:
/// ${'A ' if signed else 'An un'}signed integer value type.
///
/// On 32-bit platforms, `${Self}` is the same size as `${Self}32`, and
/// on 64-bit platforms, `${Self}` is the same size as `${Self}64`.
%   else:
/// ${Article} ${bits}-bit ${'' if signed else 'un'}signed integer value
/// type.
%   end
@_fixed_layout
public struct ${Self}
  : FixedWidthInteger, ${Unsigned}Integer,
    _ExpressibleByBuiltinIntegerLiteral {

  @_transparent
  public init(_builtinIntegerLiteral x: _MaxBuiltinIntegerType) {
    _value = Builtin.s_to_${u}_checked_trunc_${IntLiteral}_${BuiltinName}(x).0
  }

  /// Creates a new instance with the same memory representation as the given
  /// value.
  ///
  /// This initializer does not perform any range or overflow checking. The the
  /// resulting instance may not have the same numeric value as
  /// `bitPattern`---it is only guaranteed to use the same pattern of bits in
  /// its binary representation.
  ///
  /// - Parameter x: A value to use as the source of the new instance's binary
  ///   representation.
  @_transparent
  public init(bitPattern x: ${OtherSelf}) {
    _value = x._value
  }

%   if Self in ['Int32', 'Int64']:
%     Floating = {32 : 'Float', 64 : 'Double'}[bits]
  @available(*, unavailable,
    message: "Please use ${Self}(bitPattern: ${OtherSelf}) in combination with ${Floating}.bitPattern property.")
  public init(bitPattern x: ${Floating}) {
    Builtin.unreachable()
  }
%   end

%   for (FloatType, FloatBits) in [
%     ('Float', 32), ('Double', 64), ('Float80', 80)]:
%     (lower, upper) = getFtoIBounds(floatBits=FloatBits, intBits=int(bits), signed=signed)

%     if FloatType == 'Float80':
#if !os(Windows) && (arch(i386) || arch(x86_64))
%     end

  @_transparent
  public init(_ source: ${FloatType}) {
    _precondition(source.isFinite,
      "${FloatType} value cannot be converted to ${Self} because it is either infinite or NaN")
    _precondition(source > ${str(lower)}.0,
      "${FloatType} value cannot be converted to ${Self} because the result would be less than ${Self}.min")
    _precondition(source < ${str(upper)}.0,
      "${FloatType} value cannot be converted to ${Self} because the result would be greater than ${Self}.max")
    self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value)
  }

  @_transparent
  public init?(exactly source: ${FloatType}) {
    self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value)
    if ${FloatType}(self) != source {
      return nil
    }
  }

%     if FloatType == 'Float80':
#endif
%     end

%   end

  @_transparent
  public static func == (lhs: ${Self}, rhs: ${Self}) -> Bool {
    return Bool(Builtin.cmp_eq_Int${bits}(lhs._value, rhs._value))
  }

  @_transparent
  public static func < (lhs: ${Self}, rhs: ${Self}) -> Bool {
    return Bool(Builtin.cmp_${u}lt_Int${bits}(lhs._value, rhs._value))
  }

// FIXME(integers): pending optimizer work on handling the case where the
// boolean value is wrapped into a two-case enum and then immediately
// unwrapped. <rdar://problem/29004429>
// See corresponding definitions in the FixedWidthInteger extension.
%       for x in binaryArithmetic['Numeric'] + binaryArithmetic["BinaryInteger"][:1]:
  @_transparent
  public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) {
%   if x.kind == '/':
    // No LLVM primitives for checking overflow of division
    // operations, so we check manually.
    if _slowPath(rhs == (0 as ${Self})) {
      _preconditionFailure("Remainder of or division by zero")
    }
%     if signed:
    if _slowPath(
      ${'lhs == %s.min && rhs == (-1 as %s)' % (Self, Self)}
    ) {
      _preconditionFailure("Overflow in remainder of or division")
    }
%     end
    let (result, overflow) =
      (Builtin.${u}${x.llvmName}_Int${bits}(lhs._value, rhs._value),
      false._value)
%   else:
    let (result, overflow) =
      Builtin.${u}${x.llvmName}_with_overflow_Int${bits}(
        lhs._value, rhs._value, true._value)
%   end
    Builtin.condfail(overflow)
    lhs = ${Self}(result)
  }
%       end
// end of FIXME(integers)

%       for x in chain(*binaryArithmetic.values()):

  @_transparent
  public func ${x.name}ReportingOverflow(
    ${x.firstArg} other: ${Self}
  ) -> (partialValue: ${Self}, overflow: ArithmeticOverflow) {

%         if x.kind == '/':
    // No LLVM primitives for checking overflow of division
    // operations, so we check manually.
    if _slowPath(
      other == (0 as ${Self})
      ${'|| self == %s.min && other == (-1 as %s)' % (Self, Self) if signed else ''}
    ) {
      return (partialValue: self, overflow: .overflow)
    }

    let (newStorage, overflow) = (
      Builtin.${u}${x.llvmName}_Int${bits}(self._value, other._value),
      false._value)

%         else:

    let (newStorage, overflow)
    = Builtin.${u}${x.llvmName}_with_overflow_Int${bits}(
      self._value, other._value, false._value)
%         end

    return (
      partialValue: ${Self}(newStorage),
      overflow: ArithmeticOverflow(Bool(overflow)))
  }
%       end

  @_transparent
  public static func %=(_ lhs: inout ${Self}, _ rhs: ${Self}) {
    // No LLVM primitives for checking overflow of division
    // operations, so we check manually.
    if _slowPath(rhs == (0 as ${Self})) {
      _preconditionFailure("Remainder of division by zero")
    }
%     if signed:
    if _slowPath(
      ${'lhs == %s.min && rhs == (-1 as %s)' % (Self, Self)}
    ) {
      _preconditionFailure("Overflow in remainder of division")
    }
%     end

    let (newStorage, _) = (
      Builtin.${u}rem_Int${bits}(lhs._value, rhs._value),
      false._value)
    lhs = ${Self}(newStorage)
  }

  @_transparent
  public init(_ _value: Builtin.Int${bits}) {
    self._value = _value
  }

  // FIXME(integers): in order to remove this, the simd.swift.gyb should be
  // updated
  @_transparent
  public init(_bits: Builtin.Int${bits}) {
    self._value = _bits
  }

% for x in binaryBitwise:
  @_transparent
  public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) {
    lhs = ${Self}(Builtin.${x.llvmName}_Int${bits}(lhs._value, rhs._value))
  }
% end

% for x in maskingShifts:

${assignmentOperatorComment(x.operator, True)}
  @_transparent
  public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) {
    let rhs_ = rhs & ${bits - 1}
    lhs = ${Self}(
      Builtin.${x.llvmName(signed)}_Int${bits}(lhs._value, rhs_._value))
  }

% end

  @_transparent
  public static var bitWidth : Int { return ${bits} }

  @_transparent
  public var leadingZeroBitCount: Int {
    return Int(
      ${Self}(
        Builtin.int_ctlz_Int${bits}(self._value, false._value)
      )._lowUWord._value)
  }

  @_transparent
  public var trailingZeroBitCount: Int {
    return Int(
      ${Self}(
        Builtin.int_cttz_Int${bits}(self._value, false._value)
      )._lowUWord._value)
  }

  @_transparent
  public var nonzeroBitCount: Int {
    return Int(
      ${Self}(
        Builtin.int_ctpop_Int${bits}(self._value)
      )._lowUWord._value)
  }

  @_transparent
  public func _word(at n: Int) -> UInt {
    _precondition(n >= 0, "Negative word index")
    if _fastPath(n < _countRepresentedWords) {
      let shift = UInt(n._value) &* ${word_bits}
      let bitWidth = UInt(self.bitWidth._value)
      _sanityCheck(shift < bitWidth)
      return (self &>> ${Self}(_truncatingBits: shift))._lowUWord
    }
% if signed:
    return self < (0 as ${Self}) ? ~0 : 0
% else:
    return 0
% end
  }


  @_transparent
  public // transparent
  var _lowUWord: UInt {
    % truncOrExt = z + 'ext' if bits <= word_bits else 'trunc'
    return UInt(
      Builtin.${truncOrExt}OrBitCast_Int${bits}_Int${word_bits}(_value)
    )
  }

  @_transparent
  public // transparent
  init(_truncatingBits bits: UInt) {
    % truncOrExt = 'zext' if bits > word_bits else 'trunc'
    self.init(
      Builtin.${truncOrExt}OrBitCast_Int${word_bits}_Int${bits}(bits._value))
  }

  public typealias Magnitude = ${U}${Self}

% if signed:
  @_transparent
  public var magnitude: U${Self} {
    let base = U${Self}(_value)
    return self < (0 as ${Self}) ? ~base + 1 : base
  }
% end

%   dbits = bits*2
  // FIXME(integers): tests
  public func multipliedFullWidth(by other: ${Self})
  -> (high: ${Self}, low: ${Self}.Magnitude) {
%   # 128 bit types are not provided by the 32-bit LLVM
%   if word_bits == 32 and bits == 64:
    // FIXME(integers): implement
    fatalError("Operation is not supported")
%   else:
    let lhs_ = Builtin.${z}ext_Int${bits}_Int${dbits}(self._value)
    let rhs_ = Builtin.${z}ext_Int${bits}_Int${dbits}(other._value)

    let res = Builtin.mul_Int${dbits}(lhs_, rhs_)
    let low = ${Self}.Magnitude(Builtin.truncOrBitCast_Int${dbits}_Int${bits}(res))
    let shift = Builtin.zextOrBitCast_Int8_Int${dbits}(UInt8(${bits})._value)
    let shifted = Builtin.ashr_Int${dbits}(res, shift)
    let high = ${Self}(Builtin.truncOrBitCast_Int${dbits}_Int${bits}(shifted))
    return (high: high, low: low)
%   end
  }

  // FIXME(integers): tests
  public func dividingFullWidth(
    _ dividend: (high: ${Self}, low: ${Self}.Magnitude)
  ) -> (quotient: ${Self}, remainder: ${Self}) {
%   # 128 bit types are not provided by the 32-bit LLVM
%   #if word_bits == 32 and bits == 64:
%   if bits == 64:
    let lhs = DoubleWidth<${Self}>(dividend)
    let rhs = DoubleWidth<${Self}>(self)

    let (quotient, remainder) = lhs.quotientAndRemainder(dividingBy: rhs)
    // FIXME(integers): check for high words in quotient and remainder
    return (${Self}(quotient.low), ${Self}(remainder.low))
%   else:
    // FIXME(integers): handle division by zero and overflows
    _precondition(self != 0, "Division by zero")
    let lhsHigh = Builtin.${z}ext_Int${bits}_Int${dbits}(dividend.high._value)
    let shift = Builtin.zextOrBitCast_Int8_Int${dbits}(UInt8(${bits})._value)
    let lhsHighShifted = Builtin.shl_Int${dbits}(lhsHigh, shift)
    let lhsLow = Builtin.zext_Int${bits}_Int${dbits}(dividend.low._value)
    let lhs_ = Builtin.or_Int${dbits}(lhsHighShifted, lhsLow)
    let rhs_ = Builtin.${z}ext_Int${bits}_Int${dbits}(self._value)

    let quotient_ = Builtin.${u}div_Int${dbits}(lhs_, rhs_)
    let remainder_ = Builtin.${u}rem_Int${dbits}(lhs_, rhs_)

    let quotient = ${Self}(
      Builtin.truncOrBitCast_Int${dbits}_Int${bits}(quotient_))
    let remainder = ${Self}(
      Builtin.truncOrBitCast_Int${dbits}_Int${bits}(remainder_))

    return (quotient: quotient, remainder: remainder)
%   end
  }

  /// A representation of this integer with the byte order swapped.
  @_transparent
  public var byteSwapped: ${Self} {
%   if bits <= 8:
    return self
%   else:
    return ${Self}(Builtin.int_bswap_${BuiltinName}(_value))
%   end
  }

  // Implementation details

  public var _value: Builtin.Int${bits}

% if self_type.is_word:
  @_transparent
  public // @testable
  init(_ _v: Builtin.Word) {
% if BuiltinName == 'Int32':
    self._value = Builtin.truncOrBitCast_Word_Int32(_v)
% elif BuiltinName == 'Int64':
    self._value = Builtin.zextOrBitCast_Word_Int64(_v)
% end
  }

  @_transparent
  public // @testable
  var _builtinWordValue: Builtin.Word {
% if BuiltinName == 'Int32':
    return Builtin.zextOrBitCast_Int32_Word(_value)
% elif BuiltinName == 'Int64':
    return Builtin.truncOrBitCast_Int64_Word(_value)
% end
  }
% end

  @available(swift, obsoleted: 4.0, message: "Use initializers instead")
  public func to${U}IntMax() -> ${U}IntMax {
    return numericCast(self)
  }

  @available(swift, obsoleted: 4, message: "Use bitWidth instead.")
  public static var _sizeInBits: ${Self} { return ${bits} }

  @available(swift, obsoleted: 4)
  public static var _sizeInBytes: ${Self} { return ${bits}/8 }

  @inline(__always)
  public func signum() -> ${Self} {
    let isPositive = ${Self}(Builtin.zext_Int1_Int${bits}(
      (self > (0 as ${Self}))._value))
    return isPositive | (self &>> ${bits - 1})
  }
}
%# end of concrete type: ${Self}

extension ${Self} {
  // FIXME(integers): implement me in a less terrible way
  public init<T : FloatingPoint>(_ source: T) {
%   for (FloatType, FloatBits) in [
%     ('Float', 32), ('Double', 64), ('Float80', 80)]:
%     if FloatType == 'Float80':
#if !os(Windows) && (arch(i386) || arch(x86_64))
%     end
    if source is ${FloatType} {
      self.init(source as! ${FloatType})
      return
    }
%     if FloatType == 'Float80':
#endif
%     end
%   end
    _preconditionFailure("Conversion is not supported")
  }
}


extension ${Self} : Hashable {
  /// The integer's hash value.
  ///
  /// The hash value is not guaranteed to be stable across different
  /// invocations of the same program. Do not persist the hash value across
  /// program runs.
  public var hashValue: Int {
    @inline(__always)
    get {
% if bits <= word_bits and signed:
      // Sign extend the value.
      return Int(self)
% elif bits <= word_bits and not signed:
      // Sign extend the value.
      return Int(${OtherSelf}(bitPattern: self))
% elif bits == word_bits * 2:
      // We have twice as many bits as we need to return.
      return
        Int(extendingOrTruncating: self) ^
        Int(extendingOrTruncating: self &>> 32)
% else:
      _Unimplemented()
% end
    }
  }
}


// Create an ambiguity when indexing or slicing
// Range[OfStrideable]<${Self}> outside a generic context.  See
// Range.swift for details.
extension ${Self} {
  public typealias _DisabledRangeIndex = ${Self}
}


% for src_type in all_integer_types(word_bits):
%   srcBits = src_type.bits
%   srcSigned = src_type.is_signed
%   Src = src_type.stdlib_name
%   if should_define_truncating_bit_pattern_init(src_ty=src_type, dst_ty=self_type):
extension ${Self} {
  /// Creates a new instance with the same bitwise representation as the least
  /// significant bits of the given value.
  ///
  /// This initializer performs no range or overflow checking. The resulting
  /// instance may have a different numeric value from `source`.
  ///
  /// - Parameter source: An integer to use as the source of the new value's
  ///   bit pattern.
  @available(swift, obsoleted: 4.0, renamed: "init(extendingOrTruncating:)")
  @_transparent
  public init(truncatingBitPattern source: ${Src}) {
    let src = source._value
%     if self_type.bits == src_type.bits:
    let dstNotWord = src
%     else:
    let dstNotWord = Builtin.trunc_Int${srcBits}_Int${bits}(src)
%     end
    self._value = dstNotWord
  }
}
%   end
% end


// FIXME(integers): this section here is to help the typechecker,
// as it seems to have problems with a pattern where the nonmutating operation
// is defined on a protocol in terms of a mutating one that is itself defined
// on concrete types.
extension ${Self} {

%   for x in binaryBitwise + maskingShifts + list(chain(*binaryArithmetic.values())):

  @_transparent
  public static func ${x.operator}(_ lhs: ${Self}, _ rhs: ${Self}) -> ${Self} {
    var lhs = lhs
    lhs ${x.operator}= rhs
    return lhs
  }

%   end

%   for op in maskingShifts:

  @available(swift, obsoleted: 4)
  @_transparent
  public static func ${op.nonMaskingOperator}(
    lhs: ${Self}, rhs: ${Self}
  ) -> ${Self} {
    var lhs = lhs
    ${op.helper}Generic(&lhs, rhs)
    return lhs
  }

  @available(swift, obsoleted: 4)
  @_transparent
  public static func ${op.nonMaskingOperator}=(
    lhs: inout ${Self}, rhs: ${Self}
  ) {
    ${op.helper}Generic(&lhs, rhs)
  }

%   end
}


% if signed:
// TODO: Consider removing the underscore.
/// Returns the argument and specifies that the value is not negative.
/// It has only an effect if the argument is a load or call.
@_transparent
public func _assumeNonNegative(_ x: ${Self}) -> ${Self} {
  _sanityCheck(x >= (0 as ${Self}))
  return ${Self}(Builtin.assumeNonNegative_${BuiltinName}(x._value))
}
% end

//===--- end of FIXME(integers) -------------------------------------------===//

% end # end of concrete FixedWidthInteger section


/// Returns the given integer as the equivalent value in a different integer
/// type.
///
/// The `numericCast(_:)` function traps on overflow in `-O` and `-Onone`
/// builds.
///
/// You can use `numericCast(_:)` to convert a value when the destination type
/// can be inferred from the context. In the following example, the
/// `random(in:)` function uses `numericCast(_:)` twice to convert the
/// argument and return value of the `arc4random_uniform(_:)` function to the
/// appropriate type.
///
///     func random(in range: Range<Int>) -> Int {
///         return numericCast(arc4random_uniform(numericCast(range.count)))
///             + range.lowerBound
///     }
///
///     let number = random(in: -10...<10)
///     // number == -3, perhaps
///
/// - Parameter x: The integer to convert, and instance of type `T`.
/// - Returns: The value of `x` converted to type `U`.
@_transparent
public func numericCast<T : BinaryInteger, U : BinaryInteger>(_ x: T) -> U {
  return U(x)
}

// FIXME(integers): switch to using `FixedWidthInteger.unsafeAdding`
internal func _unsafePlus(_ lhs: Int, _ rhs: Int) -> Int {
#if INTERNAL_CHECKS_ENABLED
  return lhs + rhs
#else
  return lhs &+ rhs
#endif
}

// FIXME(integers): switch to using `FixedWidthInteger.unsafeSubtracting`
internal func _unsafeMinus(_ lhs: Int, _ rhs: Int) -> Int {
#if INTERNAL_CHECKS_ENABLED
  return lhs - rhs
#else
  return lhs &- rhs
#endif
}

// Swift 3 compatibility APIs

@available(swift, obsoleted: 4, renamed: "BinaryInteger")
public typealias Integer = BinaryInteger

@available(swift, obsoleted: 4, renamed: "BinaryInteger")
public typealias IntegerArithmetic = BinaryInteger

@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
public typealias SignedNumber = SignedNumeric & Comparable

@available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.")
public typealias AbsoluteValuable = SignedNumeric & Comparable

@available(swift, obsoleted: 4, renamed: "SignedInteger")
public typealias _SignedInteger = SignedInteger

extension SignedNumeric where Self : Comparable {
  @available(swift, obsoleted: 4, message: "Please use the 'abs(_:)' free function.")
  @_transparent
  public static func abs(_ x: Self) -> Self {
    return Swift.abs(x)
  }
}

@available(swift, obsoleted: 4)
extension BinaryInteger {
  @available(swift, obsoleted: 4)
  public func toIntMax() -> IntMax {
    return IntMax(self)
  }
}

extension UnsignedInteger {
  @available(swift, obsoleted: 4)
  public func toUIntMax() -> UIntMax {
    return UIntMax(self)
  }
}

// FIXME(integers): These overloads allow expressions like the following in
// Swift 3 compatibility mode:
//    let x = 1 << i32
//    f(i32: x)
// At the same time, since they are obsolete in Swift 4, this will not cause
// `u8 << -1` to fail due to an overflow in an unsigned value.
extension FixedWidthInteger {

%   for op in maskingShifts:

  @available(swift, obsoleted: 4)
  @_transparent
  public static func ${op.nonMaskingOperator}(
    lhs: Self, rhs: Self
  ) -> Self {
    var lhs = lhs
    ${op.helper}Generic(&lhs, rhs)
    return lhs
  }

  @available(swift, obsoleted: 4)
  @_transparent
  public static func ${op.nonMaskingOperator}=(
    lhs: inout Self, rhs: Self
  ) {
    ${op.helper}Generic(&lhs, rhs)
  }

%   end

}

%{
overflowingOps = [
  ('add', 'adding', ''),
  ('subtract', 'subtracting', ''),
  ('multiply', 'multiplied', 'by:'),
  ('divide', 'divided', 'by:'),
  ('remainder', 'remainder', 'dividingBy:'),
]
}%

extension FixedWidthInteger {
% for oldPrefix, newPrefix, argLabel in overflowingOps:
  @available(swift, obsoleted: 4, message: "Use ${newPrefix}ReportingOverflow(${argLabel or '_:'}) instead.")
  @_transparent
  public static func ${oldPrefix}WithOverflow(
    _ lhs: Self, _ rhs: Self
  ) -> (Self, overflow: Bool) {
    let (partialValue, overflow) =
      lhs.${newPrefix}ReportingOverflow(${argLabel} rhs)
    return (partialValue, overflow == .overflow)
  }

% end
}

extension BinaryInteger {
% for oldPrefix, newPrefix, argLabel in overflowingOps:
  @available(swift, obsoleted: 3.2,
    message: "Please use FixedWidthInteger protocol as a generic constraint and ${newPrefix}ReportingOverflow(${argLabel or '_:'}) method instead.")
  public static func ${oldPrefix}WithOverflow(
    _ lhs: Self, _ rhs: Self
  ) -> (Self, overflow: Bool) {
    fatalError("Unavailable")
  }
% end
}

// FIXME(integers): Absence of &+ causes ambiguity in the code like the
// following:
//    func f<T : SignedInteger>(_ x: T, _ y: T) {
//      var _  = (x &+ (y - 1)) < x
//    }
//  Compiler output:
//  error: ambiguous reference to member '-'
//    var _  = (x &+ (y - 1)) < x
//                      ^
%   maskingOpsSwift3 = [
%     ('&+', '_maskingAdd', 'adding'),
%     ('&-', '_maskingSubtract', 'subtracting')]
extension SignedInteger {
%   for (op, helper, _) in maskingOpsSwift3:
  public static func ${helper}(_ lhs: Self, _ rhs: Self) -> Self {
    fatalError("Should be overridden in a more specific type")
  }

  @available(swift, obsoleted: 4.0,
      message: "Please use 'FixedWidthInteger' instead of 'SignedInteger' to get '${op}' in generic code.")
  public static func ${op} (lhs: Self, rhs: Self) -> Self {
    return ${helper}(lhs, rhs)
  }
%   end
}

extension SignedInteger where Self : FixedWidthInteger {
%   for (op, helper, action) in maskingOpsSwift3:
  // This overload is supposed to break the ambiguity between the
  // implementations on SignedInteger and FixedWidthInteger
  public static func ${op} (lhs: Self, rhs: Self) -> Self {
    return ${helper}(lhs, rhs)
  }
  @_transparent
  public static func ${helper}(_ lhs: Self, _ rhs: Self) -> Self {
    return lhs.${action}ReportingOverflow(rhs).partialValue
  }
%   end
}
